docs/interfaces/MatterAccessory.html
Matter Accessory - Plugin API Interface
This is the main interface that plugin developers use to register Matter accessories with Homebridge.
For composed devices (devices with multiple subcomponents), use the parts array to define child endpoints. Each part appears as a separate device in the Home app.
interface MatterAccessory<T extends UnknownContext = UnknownContext> {
_eventEmitter?: MatterAccessoryEventEmitter;
clusters?: {
airQuality?: Partial<{ airQuality: number }>;
booleanState?: Partial<{ stateValue: boolean }>;
carbonMonoxideConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
colorControl?: Partial<ColorControlState>;
doorLock?: Partial<DoorLockState>;
fanControl?: Partial<FanControlState>;
identify?: Partial<{ identifyTime: number; identifyType: number }>;
illuminanceMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
minMeasuredValue?: number | null;
},
>;
levelControl?: Partial<LevelControlState>;
nitrogenDioxideConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
occupancySensing?: Partial<
{
occupancy: { occupied: boolean };
occupancySensorType?: number;
occupancySensorTypeBitmap?: {
physicalContact?: boolean;
pir?: boolean;
ultrasonic?: boolean;
};
},
>;
onOff?: Partial<OnOffState>;
ozoneConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
pm10ConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
pm25ConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
powerSource?: Partial<PowerSourceState>;
relativeHumidityMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
minMeasuredValue?: number | null;
},
>;
rvcCleanMode?: Partial<RvcCleanModeState>;
rvcOperationalState?: Partial<RvcOperationalState>;
rvcRunMode?: Partial<RvcRunModeState>;
serviceArea?: Partial<ServiceAreaState>;
switch?: Partial<{ currentPosition: number; numberOfPositions?: number }>;
temperatureMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
minMeasuredValue?: number | null;
},
>;
thermostat?: Partial<ThermostatState>;
valveConfigurationAndControl?: Partial<ValveConfigurationAndControlState>;
windowCovering?: Partial<WindowCoveringState>;
} & { [clusterName: string]: Record<string, unknown> };
context: T;
deviceType: EndpointType;
displayName: string;
firmwareRevision?: string;
getState?: (cluster: string, attribute: string) => unknown;
handlers?: {
colorControl?: Partial<ColorControlHandlers>;
doorLock?: Partial<DoorLockHandlers>;
fanControl?: Partial<FanControlHandlers>;
identify?: Partial<IdentifyHandlers>;
levelControl?: Partial<LevelControlHandlers>;
onOff?: Partial<OnOffHandlers>;
rvcCleanMode?: Partial<RvcCleanModeHandlers>;
rvcOperationalState?: Partial<RvcOperationalStateHandlers>;
rvcRunMode?: Partial<RvcRunModeHandlers>;
serviceArea?: Partial<ServiceAreaHandlers>;
thermostat?: Partial<ThermostatHandlers>;
valveConfigurationAndControl?: Partial<
ValveConfigurationAndControlHandlers,
>;
windowCovering?: Partial<WindowCoveringHandlers>;
} & { [clusterName: string]: MatterClusterHandlers };
hardwareRevision?: string;
manufacturer: string;
model: string;
parts?: MatterAccessoryPart[];
serialNumber: string;
softwareVersion?: string;
UUID: string;
}
_eventEmitter?clusters?contextdeviceTypedisplayNamefirmwareRevision?getState?handlers?hardwareRevision?manufacturermodelparts?serialNumbersoftwareVersion?UUID
Optional_eventEmitter_eventEmitter?: MatterAccessoryEventEmitter
Event emitter for accessory lifecycle events.
Only available for external accessories published via api.matter?.publishExternalAccessories(). This property is undefined for accessories registered via api.matter?.registerPlatformAccessories().
The event emitter is created automatically when the accessory is published and allows plugins to listen for the 'ready' event (fired when the Matter server starts).
HAP Equivalent: Similar to accessing events on PlatformAccessory._associatedHAPAccessory
const accessory: MatterAccessory = { ... };api.matter?.publishExternalAccessories('plugin', [accessory]);// Listen for when the accessory is ready on the networkaccessory._eventEmitter?.on(MatterAccessoryEventTypes.READY, (port) => { console.log(`Accessory ready on port ${port}`); // Safe to start device integration, polling, webhooks, etc.});Copy
MatterAccessoryEventTypes for available events
Optionalclustersclusters?: {
airQuality?: Partial<{ airQuality: number }>;
booleanState?: Partial<{ stateValue: boolean }>;
carbonMonoxideConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
colorControl?: Partial<ColorControlState>;
doorLock?: Partial<DoorLockState>;
fanControl?: Partial<FanControlState>;
identify?: Partial<{ identifyTime: number; identifyType: number }>;
illuminanceMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
minMeasuredValue?: number | null;
},
>;
levelControl?: Partial<LevelControlState>;
nitrogenDioxideConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
occupancySensing?: Partial<
{
occupancy: { occupied: boolean };
occupancySensorType?: number;
occupancySensorTypeBitmap?: {
physicalContact?: boolean;
pir?: boolean;
ultrasonic?: boolean;
};
},
>;
onOff?: Partial<OnOffState>;
ozoneConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
pm10ConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
pm25ConcentrationMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
measurementMedium: number;
measurementUnit?: number;
minMeasuredValue?: number | null;
},
>;
powerSource?: Partial<PowerSourceState>;
relativeHumidityMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
minMeasuredValue?: number | null;
},
>;
rvcCleanMode?: Partial<RvcCleanModeState>;
rvcOperationalState?: Partial<RvcOperationalState>;
rvcRunMode?: Partial<RvcRunModeState>;
serviceArea?: Partial<ServiceAreaState>;
switch?: Partial<{ currentPosition: number; numberOfPositions?: number }>;
temperatureMeasurement?: Partial<
{
maxMeasuredValue?: number
| null;
measuredValue: number | null;
minMeasuredValue?: number | null;
},
>;
thermostat?: Partial<ThermostatState>;
valveConfigurationAndControl?: Partial<ValveConfigurationAndControlState>;
windowCovering?: Partial<WindowCoveringState>;
} & { [clusterName: string]: Record<string, unknown> }
Initial cluster states Key is the cluster name, value is an object of attribute name -> value
Known clusters (onOff, levelControl, colorControl, etc.) provide full autocomplete. Unknown clusters are still supported with the fallback Record<string, unknown> type.
clusters: { onOff: { onOff: true }, levelControl: { currentLevel: 127, minLevel: 1, maxLevel: 254 },}Copy
Note: If using parts, this is optional (main accessory may only be a container)
context: T
Plugin developer storage - persists across restarts This is a way for plugin developers to store custom data with their accessory Similar to PlatformAccessory.context for HAP accessories
deviceType: EndpointType
Matter device type (e.g., OnOffLightDevice, DimmableLightDevice, etc.)
displayName: string
Display name for the accessory
OptionalfirmwareRevisionfirmwareRevision?: string
Firmware revision (optional)
OptionalgetStategetState?: (cluster: string, attribute: string) => unknown
Optional: Get current state handler Called when a Matter controller reads an attribute If not provided, the last set value is returned
- cluster: string
Cluster name (e.g., 'onOff', 'levelControl')
- attribute: string
Attribute name to read
Current value of the attribute
Optionalhandlershandlers?: {
colorControl?: Partial<ColorControlHandlers>;
doorLock?: Partial<DoorLockHandlers>;
fanControl?: Partial<FanControlHandlers>;
identify?: Partial<IdentifyHandlers>;
levelControl?: Partial<LevelControlHandlers>;
onOff?: Partial<OnOffHandlers>;
rvcCleanMode?: Partial<RvcCleanModeHandlers>;
rvcOperationalState?: Partial<RvcOperationalStateHandlers>;
rvcRunMode?: Partial<RvcRunModeHandlers>;
serviceArea?: Partial<ServiceAreaHandlers>;
thermostat?: Partial<ThermostatHandlers>;
valveConfigurationAndControl?: Partial<
ValveConfigurationAndControlHandlers,
>;
windowCovering?: Partial<WindowCoveringHandlers>;
} & { [clusterName: string]: MatterClusterHandlers }
Handlers for Matter commands (Home app -> Device)
These handlers are called when a user controls the accessory via the Home app. Use handlers to send commands to your actual device (cloud API, local network, etc.).
Known clusters (onOff, levelControl, colorControl, etc.) provide full autocomplete for handler method names and argument types.
handlers: { onOff: { on: async () => { await device.turnOn() }, off: async () => { await device.turnOff() }, }, levelControl: { moveToLevel: async (args) => { // args is typed as LevelControl.MoveToLevelRequest await device.setBrightness(args?.level ?? 0) }, },}Copy
OptionalhardwareRevisionhardwareRevision?: string
Hardware revision (optional)
manufacturer: string
Manufacturer name
model: string
Model name/identifier
Optionalpartsparts?: MatterAccessoryPart[]
Optional: Array of child endpoints (parts) for composed devices
Use this to create devices with multiple independent subcomponents, such as:
Each part appears as a separate device in the Home app and can be controlled independently.
Example:
parts: [{ id: 'outlet-1', displayName: 'Outlet 1', deviceType: api.matter!.deviceTypes.OnOffOutlet, clusters: { onOff: { onOff: false } }, handlers: { onOff: { on: async (args, context) => { console.log(`Part ${context.partId} turned on`) await controlOutlet(1, true) } } } }, // ... more outlets]Copy
serialNumber: string
Serial number for the device
OptionalsoftwareVersionsoftwareVersion?: string
Software version (optional)
UUID: string
Unique identifier for this accessory (must be unique across all accessories)
Member Visibility
ThemeOSLightDark
Properties _eventEmitterclusterscontextdeviceTypedisplayNamefirmwareRevisiongetStatehandlershardwareRevisionmanufacturermodelpartsserialNumbersoftwareVersionUUID