homebridge
Version:
HomeKit support for the impatient
104 lines • 5.02 kB
JavaScript
/**
* ValveConfigurationAndControl Cluster Behavior
*
* Handles open/close commands for water valves and irrigation controllers.
*/
import { ValveConfigurationAndControlServer } from '@matter/main/behaviors/valve-configuration-and-control';
import { ValveConfigurationAndControl } from '@matter/main/clusters/valve-configuration-and-control';
import { Status, StatusResponseError } from '@matter/main/types';
import { MatterStatus } from '../errors.js';
import { getRegistryManager } from './EndpointContext.js';
/**
* Default ValveConfigurationAndControl Server.
*
* matter.js's base ValveConfigurationAndControlServer does NOT implement the
* open/close commands — invoking them throws NotImplementedError. This default
* implementation reflects the command in the cluster state, so valves without
* plugin handlers still respond to open/close from controllers and the UI.
*/
export class DefaultValveConfigurationAndControlServer extends ValveConfigurationAndControlServer {
// The request (openDuration/targetLevel) is intentionally ignored here — the
// default implementation only reflects the open/close state. The parameter
// must stay so HomebridgeValveConfigurationAndControlServer can forward it.
// eslint-disable-next-line unused-imports/no-unused-vars
async open(_request) {
this.state.currentState = ValveConfigurationAndControl.ValveState.Open;
this.state.targetState = ValveConfigurationAndControl.ValveState.Open;
}
async close() {
this.state.currentState = ValveConfigurationAndControl.ValveState.Closed;
this.state.targetState = ValveConfigurationAndControl.ValveState.Closed;
}
}
/**
* Custom ValveConfigurationAndControl Server that calls plugin handlers.
* Extends the default server so the super.open()/super.close() calls update
* the cluster state (the matter.js base would throw NotImplementedError).
*/
export class HomebridgeValveConfigurationAndControlServer extends DefaultValveConfigurationAndControlServer {
/**
* Get the registry for this behavior's endpoint
*/
getRegistry() {
return getRegistryManager(this.endpoint).getRegistry(this.endpoint.id);
}
/**
* Handle 'open' command
*/
async open(request) {
const endpointId = this.endpoint.id;
const registry = this.getRegistry();
try {
// Execute user handler
await registry.executeHandler(endpointId, 'valveConfigurationAndControl', 'open', request);
// Only reached if handler succeeded - update Matter state via super
await super.open(request);
// Sync state to cache
registry.syncStateToCache(endpointId, 'valveConfigurationAndControl', {
currentState: ValveConfigurationAndControl.ValveState.Open,
targetState: ValveConfigurationAndControl.ValveState.Open,
});
}
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 open valve: ${message}`, Status.Failure);
}
}
/**
* Handle 'close' command
*/
async close() {
const endpointId = this.endpoint.id;
const registry = this.getRegistry();
try {
// Execute user handler
await registry.executeHandler(endpointId, 'valveConfigurationAndControl', 'close');
// Only reached if handler succeeded - update Matter state via super
await super.close();
// Sync state to cache
registry.syncStateToCache(endpointId, 'valveConfigurationAndControl', {
currentState: ValveConfigurationAndControl.ValveState.Closed,
targetState: ValveConfigurationAndControl.ValveState.Closed,
});
}
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 close valve: ${message}`, Status.Failure);
}
}
}
//# sourceMappingURL=ValveConfigurationAndControlBehavior.js.map