HomeKit support for the impatient - lightweight Node.js server enabling HomeKit integration for non-native smart home devices through plugin ecosystem
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The Core Plugin API provides the main interface that plugins interact with for registration, lifecycle management, and access to HAP-NodeJS functionality. All plugins receive an API instance during initialization and use it to register their accessories and platforms.
The main API interface provided to plugins during initialization.
/**
* Main API interface provided to plugins during initialization
* Provides access to registration methods, HAP-NodeJS, and system utilities
*/
interface API {
/** API specification version (currently 2.7) */
readonly version: number;
/** Homebridge server version */
readonly serverVersion: string;
/** User class constructor for storage and path utilities */
readonly user: typeof User;
/** Complete HAP-NodeJS library access */
readonly hap: HAP;
/** Legacy HAP-NodeJS types for compatibility */
readonly hapLegacyTypes: HAPLegacyTypes;
/** PlatformAccessory constructor reference */
readonly platformAccessory: typeof PlatformAccessory;
/** Check if server version meets minimum requirement */
versionGreaterOrEqual(version: string): boolean;
/** Register a single accessory plugin */
registerAccessory(pluginIdentifier: PluginIdentifier, accessoryName: AccessoryName, constructor: AccessoryPluginConstructor): void;
/** Register a platform plugin */
registerPlatform(pluginIdentifier: PluginIdentifier, platformName: PlatformName, constructor: PlatformPluginConstructor): void;
/** Register platform accessories for caching */
registerPlatformAccessories(pluginIdentifier: PluginIdentifier, platformName: PlatformName, accessories: PlatformAccessory[]): void;
/** Update existing platform accessories */
updatePlatformAccessories(accessories: PlatformAccessory[]): void;
/** Unregister platform accessories */
unregisterPlatformAccessories(pluginIdentifier: PluginIdentifier, platformName: PlatformName, accessories: PlatformAccessory[]): void;
/** Publish accessories on separate bridges */
publishExternalAccessories(pluginIdentifier: PluginIdentifier, accessories: PlatformAccessory[]): void;
/** @deprecated Use publishExternalAccessories instead */
publishCameraAccessories(pluginIdentifier: PluginIdentifier, accessories: PlatformAccessory[]): void;
/** Listen for server startup completion */
on(event: "didFinishLaunching", listener: () => void): this;
/** Listen for server shutdown */
on(event: "shutdown", listener: () => void): this;
}Usage Examples:
// Basic plugin registration
export = (api: API) => {
// Check minimum version
if (!api.versionGreaterOrEqual("1.8.0")) {
throw new Error("This plugin requires Homebridge v1.8.0 or higher");
}
// Register an accessory
api.registerAccessory("my-plugin", "SwitchAccessory", SwitchAccessory);
// Register a platform
api.registerPlatform("my-plugin", "MyPlatform", MyPlatform);
// Listen for startup completion
api.on("didFinishLaunching", () => {
console.log("Homebridge finished launching");
});
};
// Using HAP-NodeJS through the API
class MyAccessory {
constructor(log: Logger, config: any, api: API) {
// Access Services and Characteristics
const Service = api.hap.Service;
const Characteristic = api.hap.Characteristic;
this.service = new Service.Lightbulb(config.name);
this.service.getCharacteristic(Characteristic.On)
.onGet(() => this.getState())
.onSet((value) => this.setState(value));
}
}Lifecycle events that plugins can listen for to coordinate startup and shutdown behavior.
/**
* API lifecycle events
*/
enum APIEvent {
/** Fired when all plugins have been loaded and accessories published */
DID_FINISH_LAUNCHING = "didFinishLaunching",
/** Fired when Homebridge is shutting down */
SHUTDOWN = "shutdown"
}Usage Examples:
// Wait for full startup before initializing external connections
api.on("didFinishLaunching", () => {
// Safe to connect to external services
this.connectToDeviceHub();
this.startPollingDevices();
});
// Clean up resources on shutdown
api.on("shutdown", () => {
this.disconnectFromDeviceHub();
this.cleanupResources();
});The concrete implementation of the API interface.
/**
* Concrete implementation of the API interface
* Extended with static utility methods for plugin type checking
*/
class HomebridgeAPI extends EventEmitter implements API {
readonly version: number; // API version: 2.7
readonly serverVersion: string; // Dynamic server version
readonly user: typeof User;
readonly hap: HAP;
readonly hapLegacyTypes: HAPLegacyTypes;
readonly platformAccessory: typeof PlatformAccessory;
/** Check if a plugin instance is a dynamic platform */
static isDynamicPlatformPlugin(plugin: any): plugin is DynamicPlatformPlugin;
/** Check if a plugin instance is a static platform */
static isStaticPlatformPlugin(plugin: any): plugin is StaticPlatformPlugin;
}Storage and path management utilities available through the API.
/**
* User storage and path management utilities
* All methods are static and accessed via User.methodName()
*/
class User {
/** Get path to homebridge config.json */
static configPath(): string;
/** Get path to persistent storage directory */
static persistPath(): string;
/** Get path to cached accessories directory */
static cachedAccessoryPath(): string;
/** Get base storage path */
static storagePath(): string;
/** Set custom storage path */
static setStoragePath(...storagePathSegments: string[]): void;
}Usage Examples:
// Access storage paths
const configPath = api.user.configPath(); // ~/.homebridge/config.json
const persistPath = api.user.persistPath(); // ~/.homebridge/persist/
const storagePath = api.user.storagePath(); // ~/.homebridge/
// Create plugin-specific storage
const pluginStorage = path.join(api.user.storagePath(), "my-plugin");
fs.ensureDirSync(pluginStorage);Type aliases for HAP-NodeJS library access.
/**
* Complete HAP-NodeJS library type
*/
type HAP = typeof import("hap-nodejs");
/**
* Legacy HAP-NodeJS types for backward compatibility
*/
type HAPLegacyTypes = typeof import("hap-nodejs").LegacyTypes;Usage Examples:
// Access all HAP-NodeJS functionality
const { Service, Characteristic, Categories } = api.hap;
// Use legacy types if needed
const legacyTypes = api.hapLegacyTypes;
// Create services and characteristics
const lightService = new Service.Lightbulb("My Light");
lightService.getCharacteristic(Characteristic.On)
.onGet(() => this.getPowerState());type PluginIdentifier = PluginName | ScopedPluginName;
type PluginName = string; // e.g., "homebridge-dummy"
type ScopedPluginName = string; // e.g., "@scope/homebridge-dummy"
type AccessoryName = string;
type PlatformName = string;
type AccessoryIdentifier = string; // format: "PluginIdentifier.AccessoryName"
type PlatformIdentifier = string; // format: "PluginIdentifier.PlatformName"