UNPKG

homebridge

Version:
85 lines 3.95 kB
/** * FanControl Cluster Behavior * * Handles fan control commands for fans */ import { FanControlServer } from '@matter/main/behaviors/fan-control'; import { Status, StatusResponseError } from '@matter/main/types'; import { MatterStatus } from '../errors.js'; import { getRegistryManager } from './EndpointContext.js'; /** * Custom FanControl Server that calls plugin handlers */ export class HomebridgeFanControlServer extends FanControlServer { /** * Get the registry for this behavior's endpoint */ getRegistry() { return getRegistryManager(this.endpoint).getRegistry(this.endpoint.id); } initialize() { super.initialize(); // React to fanMode attribute changes (on/off) this.reactTo(this.events.fanMode$Changed, this.#handleFanModeChange, { offline: true }); // React to percentSetting attribute changes (speed) this.reactTo(this.events.percentSetting$Changed, this.#handlePercentSettingChange, { offline: true }); } async #handleFanModeChange(value, oldValue) { const endpointId = this.endpoint.id; const registry = this.getRegistry(); try { // Execute user handler await registry.executeHandler(endpointId, 'fanControl', 'fanModeChange', { fanMode: value, oldFanMode: oldValue }); // Sync state to cache // When turning off (fanMode = 0), also set percentSetting and percentCurrent to 0 // This ensures the UI correctly reflects the off state const stateUpdate = { fanMode: value }; if (value === 0) { stateUpdate.percentSetting = 0; stateUpdate.percentCurrent = 0; } registry.syncStateToCache(endpointId, 'fanControl', stateUpdate); } catch (error) { // If user handler already threw a StatusResponseError, propagate it as-is // This sends a proper Matter protocol error response to the controller if (MatterStatus.isMatterProtocolError(error)) { throw error; } // For other errors, wrap in appropriate StatusResponseError // This prevents the endpoint from crashing and keeps the device online const message = error instanceof Error ? error.message : String(error); throw new StatusResponseError(`Failed to change fan mode: ${message}`, Status.Failure); } } async #handlePercentSettingChange(value, oldValue) { const endpointId = this.endpoint.id; const registry = this.getRegistry(); try { // Execute user handler await registry.executeHandler(endpointId, 'fanControl', 'percentSettingChange', { percentSetting: value, oldPercentSetting: oldValue }); // Sync state to cache // When setting to 0%, also set fanMode to 0 (Off) for UI consistency const stateUpdate = { percentSetting: value ?? undefined, percentCurrent: value ?? undefined, }; if (value === 0) { stateUpdate.fanMode = 0; } registry.syncStateToCache(endpointId, 'fanControl', stateUpdate); } catch (error) { // If user handler already threw a StatusResponseError, propagate it as-is // This sends a proper Matter protocol error response to the controller if (MatterStatus.isMatterProtocolError(error)) { throw error; } // For other errors, wrap in appropriate StatusResponseError // This prevents the endpoint from crashing and keeps the device online const message = error instanceof Error ? error.message : String(error); throw new StatusResponseError(`Failed to change fan speed: ${message}`, Status.Failure); } } } //# sourceMappingURL=FanControlBehavior.js.map