The Homebridge plugin system provides a comprehensive architecture for extending HomeKit functionality through standardized plugin interfaces. It supports four distinct plugin types: Accessory plugins, Dynamic Platform plugins, Static Platform plugins, and Independent Platform plugins, each designed for specific use cases and device management patterns.
The main entry point for every Homebridge plugin, called once during plugin loading.
/**
* Plugin initializer function - required default export for every plugin
* Called once when the plugin is loaded from disk
*/
interface PluginInitializer {
/**
* Initialize the plugin and register accessories/platforms
* @param api - The Homebridge API instance
*/
(api: API): void | Promise<void>;
}Usage Examples:
// Basic plugin initializer
const plugin: PluginInitializer = (api: API) => {
api.registerAccessory("my-plugin", "LightAccessory", LightAccessory);
api.registerPlatform("my-plugin", "MyPlatform", MyPlatform);
};
export = plugin;
// Async plugin initializer
const asyncPlugin: PluginInitializer = async (api: API) => {
// Perform async initialization
await initializeExternalLibrary();
api.registerAccessory("my-plugin", "AsyncAccessory", AsyncAccessory);
};
export = asyncPlugin;Enumeration of available plugin types.
/**
* Types of plugins supported by Homebridge
*/
enum PluginType {
/** Single accessory plugin */
ACCESSORY = "accessory",
/** Platform plugin (manages multiple accessories) */
PLATFORM = "platform"
}Single accessory plugins that expose one HomeKit accessory per configuration entry.
/**
* Constructor interface for accessory plugins
*/
interface AccessoryPluginConstructor {
new(logger: Logging, config: AccessoryConfig, api: API): AccessoryPlugin;
}
/**
* Interface for accessory plugin implementations
* Represents a single HomeKit accessory
*/
interface AccessoryPlugin {
/** Optional identification method called when user requests accessory identification */
identify?(): void;
/**
* Return all services exposed by this accessory
* Called once during startup - set up all event handlers before returning
*/
getServices(): Service[];
/**
* Return all controllers exposed by this accessory (optional)
* Used for camera controllers, remote controllers, etc.
*/
getControllers?(): Controller[];
}Usage Examples:
import { AccessoryPlugin, Logger, AccessoryConfig, API, Service } from "homebridge";
class LightAccessory implements AccessoryPlugin {
private service: Service;
private isOn = false;
constructor(
private log: Logger,
private config: AccessoryConfig,
private api: API
) {
this.service = new this.api.hap.Service.Lightbulb(this.config.name);
// Set up characteristic handlers
this.service.getCharacteristic(this.api.hap.Characteristic.On)
.onGet(this.getOn.bind(this))
.onSet(this.setOn.bind(this));
this.log.info("Light accessory initialized:", this.config.name);
}
identify() {
this.log.info("Identify requested for:", this.config.name);
}
getServices(): Service[] {
return [this.service];
}
private async getOn() {
this.log.debug("Getting power state:", this.isOn);
return this.isOn;
}
private async setOn(value: boolean) {
this.log.info("Setting power state to:", value);
this.isOn = value;
// Control actual device here
}
}
// Register the accessory
export = (api: API) => {
api.registerAccessory("my-plugin", "LightAccessory", LightAccessory);
};Base interface extended by all platform plugin types.
/**
* Constructor interface for platform plugins
*/
interface PlatformPluginConstructor<Config extends PlatformConfig = PlatformConfig> {
new(logger: Logging, config: Config, api: API): DynamicPlatformPlugin | StaticPlatformPlugin | IndependentPlatformPlugin;
}
/**
* Base interface for platform plugins (not exported publicly)
* Extended by specific platform plugin types
*/
interface PlatformPlugin {}Platform plugins that can dynamically add, remove, and update accessories during runtime.
/**
* Dynamic platform plugin interface
* Manages accessories that can be added/removed during runtime
* All accessories are cached to disk and restored on restart
*/
interface DynamicPlatformPlugin extends PlatformPlugin {
/**
* Called for each cached accessory restored from disk on startup
* Use this to restore event handlers and device connections
* @param accessory - The cached platform accessory to configure
*/
configureAccessory(accessory: PlatformAccessory): void;
}Usage Examples:
import { DynamicPlatformPlugin, Logger, PlatformConfig, API, PlatformAccessory } from "homebridge";
interface MyPlatformConfig extends PlatformConfig {
deviceHubUrl: string;
pollingInterval?: number;
}
class MyDynamicPlatform implements DynamicPlatformPlugin {
private accessories: PlatformAccessory[] = [];
constructor(
private log: Logger,
private config: MyPlatformConfig,
private api: API
) {
this.api.on("didFinishLaunching", () => {
this.discoverDevices();
});
}
configureAccessory(accessory: PlatformAccessory) {
this.log.info("Configuring cached accessory:", accessory.displayName);
// Restore event handlers for cached accessory
this.setupAccessoryServices(accessory);
this.accessories.push(accessory);
}
private async discoverDevices() {
// Discover devices from external service
const devices = await this.fetchDevicesFromHub();
for (const device of devices) {
const uuid = this.api.hap.uuid.generate(device.id);
let accessory = this.accessories.find(acc => acc.UUID === uuid);
if (!accessory) {
// Create new accessory
accessory = new this.api.platformAccessory(device.name, uuid);
this.setupAccessoryServices(accessory);
// Register with Homebridge
this.api.registerPlatformAccessories("my-plugin", "MyPlatform", [accessory]);
this.accessories.push(accessory);
}
// Update accessory context
accessory.context.device = device;
}
}
private setupAccessoryServices(accessory: PlatformAccessory) {
const service = accessory.getService(this.api.hap.Service.Lightbulb) ||
accessory.addService(this.api.hap.Service.Lightbulb);
service.getCharacteristic(this.api.hap.Characteristic.On)
.onGet(() => this.getDeviceState(accessory))
.onSet((value) => this.setDeviceState(accessory, value));
}
}Platform plugins that return a fixed set of accessories at startup.
/**
* Static platform plugin interface
* Returns a fixed set of accessories at startup
* Accessories are created fresh on each restart
*/
interface StaticPlatformPlugin extends PlatformPlugin {
/**
* Return all accessories provided by this platform
* Called once during startup
* @param callback - Callback to provide the accessories array
*/
accessories(callback: (accessories: AccessoryPlugin[]) => void): void;
}Usage Examples:
import { StaticPlatformPlugin, Logger, PlatformConfig, API, AccessoryPlugin } from "homebridge";
class MyStaticPlatform implements StaticPlatformPlugin {
constructor(
private log: Logger,
private config: PlatformConfig & { devices: any[] },
private api: API
) {}
accessories(callback: (accessories: AccessoryPlugin[]) => void) {
const accessories: AccessoryPlugin[] = [];
// Create accessories from config
for (const deviceConfig of this.config.devices) {
const accessory = new DeviceAccessory(this.log, deviceConfig, this.api);
accessories.push(accessory);
}
this.log.info("Created", accessories.length, "accessories");
callback(accessories);
}
}
class DeviceAccessory implements AccessoryPlugin {
private service: Service;
constructor(
private log: Logger,
private config: any,
private api: API
) {
this.service = new this.api.hap.Service.Switch(this.config.name);
this.service.getCharacteristic(this.api.hap.Characteristic.On)
.onGet(() => this.getState())
.onSet((value) => this.setState(value));
}
getServices(): Service[] {
return [this.service];
}
private async getState() {
// Return device state
return false;
}
private async setState(value: boolean) {
// Set device state
this.log.info("Setting", this.config.name, "to", value);
}
}Platform plugins that don't expose any accessories but perform background tasks.
/**
* Independent platform plugin interface
* Performs background tasks without exposing accessories to HomeKit
* Used for services, integrations, or system utilities
*/
interface IndependentPlatformPlugin extends PlatformPlugin {
// No required methods - plugin handles its own lifecycle
}Usage Examples:
import { IndependentPlatformPlugin, Logger, PlatformConfig, API } from "homebridge";
class SystemMonitorPlatform implements IndependentPlatformPlugin {
private monitoringInterval?: NodeJS.Timeout;
constructor(
private log: Logger,
private config: PlatformConfig & { interval?: number },
private api: API
) {
this.api.on("didFinishLaunching", () => {
this.startMonitoring();
});
this.api.on("shutdown", () => {
this.stopMonitoring();
});
}
private startMonitoring() {
const interval = this.config.interval || 60000; // 1 minute default
this.monitoringInterval = setInterval(() => {
this.checkSystemHealth();
}, interval);
this.log.info("System monitoring started");
}
private stopMonitoring() {
if (this.monitoringInterval) {
clearInterval(this.monitoringInterval);
this.monitoringInterval = undefined;
}
this.log.info("System monitoring stopped");
}
private checkSystemHealth() {
// Perform system health checks
this.log.debug("System health check completed");
}
}interface AccessoryConfig extends Record<string, any> {
/** Accessory type identifier */
accessory: string;
/** Display name for the accessory */
name: string;
/** Optional custom UUID base */
uuid_base?: string;
/** Optional bridge configuration for child bridges */
_bridge?: BridgeConfiguration;
}
interface PlatformConfig extends Record<string, any> {
/** Platform type identifier */
platform: string;
/** Optional display name for the platform */
name?: string;
/** Optional bridge configuration for child bridges */
_bridge?: BridgeConfiguration;
}