HomeKit support for the impatient - lightweight Node.js server enabling HomeKit integration for non-native smart home devices through plugin ecosystem
npx @tessl/cli install tessl/npm-homebridge@1.11.0Homebridge is a lightweight Node.js server that emulates Apple's HomeKit API, enabling HomeKit integration for smart home devices that don't natively support HomeKit. It acts as a bridge between iOS HomeKit API and various third-party smart home device APIs through a comprehensive plugin ecosystem, allowing users to control non-HomeKit devices with Siri voice commands and the Home app.
npm install -g homebridgeimport type { API, Logger, PlatformAccessory } from "homebridge";For CommonJS:
const { API, Logger, PlatformAccessory } = require("homebridge");import type { API, Logger, PlatformAccessory, AccessoryPlugin, PluginInitializer } from "homebridge";
// Plugin initializer - required default export
const plugin: PluginInitializer = (api: API) => {
api.registerAccessory("my-plugin", "MyAccessory", MyAccessory);
};
// Accessory implementation
class MyAccessory implements AccessoryPlugin {
private service: any;
constructor(private log: Logger, private config: any, private api: API) {
this.service = new this.api.hap.Service.Lightbulb(this.config.name);
this.service.getCharacteristic(this.api.hap.Characteristic.On)
.onGet(this.getOn.bind(this))
.onSet(this.setOn.bind(this));
}
getServices(): any[] {
return [this.service];
}
private async getOn() {
this.log.info("Getting light state");
return false; // Return current state
}
private async setOn(value: boolean) {
this.log.info("Setting light state to:", value);
// Control your device here
}
}
export = plugin;Homebridge is built around several key architectural components:
APIPlatformAccessoryThe main API interface that plugins interact with, providing registration methods, lifecycle events, and access to HAP-NodeJS functionality.
interface API {
readonly version: string;
readonly serverVersion: string;
readonly user: User;
readonly hap: HAP;
readonly hapLegacyTypes: HAPLegacyTypes;
readonly platformAccessory: typeof PlatformAccessory;
versionGreaterOrEqual(version: string): boolean;
registerAccessory(pluginIdentifier: PluginIdentifier, accessoryName: AccessoryName, constructor: AccessoryPluginConstructor): void;
registerPlatform(pluginIdentifier: PluginIdentifier, platformName: PlatformName, constructor: PlatformPluginConstructor): void;
registerPlatformAccessories(pluginIdentifier: PluginIdentifier, platformName: PlatformName, accessories: PlatformAccessory[]): void;
updatePlatformAccessories(accessories: PlatformAccessory[]): void;
unregisterPlatformAccessories(pluginIdentifier: PluginIdentifier, platformName: PlatformName, accessories: PlatformAccessory[]): void;
publishExternalAccessories(pluginIdentifier: PluginIdentifier, accessories: PlatformAccessory[]): void;
on(event: "didFinishLaunching", listener: () => void): this;
on(event: "shutdown", listener: () => void): this;
}Comprehensive plugin architecture supporting multiple plugin types with standardized interfaces for accessory and platform development.
interface PluginInitializer {
(api: API): void | Promise<void>;
}
enum PluginType {
ACCESSORY = "accessory",
PLATFORM = "platform"
}
interface AccessoryPlugin {
identify?(): void;
getServices(): Service[];
getControllers?(): Controller[];
}
interface DynamicPlatformPlugin {
configureAccessory(accessory: PlatformAccessory): void;
}Persistent accessory wrapper system that provides caching, context storage, and lifecycle management for HomeKit accessories.
class PlatformAccessory {
constructor(displayName: string, uuid: string, category?: Categories);
readonly displayName: string;
readonly UUID: string;
readonly category: Categories;
readonly services: Service[];
context: UnknownContext;
updateDisplayName(displayName: string): void;
addService(service: Service | typeof Service, displayName?: string, subtype?: string): Service;
removeService(service: Service): void;
getService(name: string | typeof Service): Service | undefined;
getServiceById(name: string | typeof Service, subtype: string): Service | undefined;
configureController(controller: Controller): void;
removeController(controller: Controller): void;
}Structured logging framework with prefixes, log levels, and formatting options for plugin debugging and system monitoring.
interface Logger {
readonly prefix: string;
info(message: string, ...parameters: any[]): void;
success(message: string, ...parameters: any[]): void;
warn(message: string, ...parameters: any[]): void;
error(message: string, ...parameters: any[]): void;
debug(message: string, ...parameters: any[]): void;
log(level: LogLevel, message: string, ...parameters: any[]): void;
}
enum LogLevel {
INFO = "info",
SUCCESS = "success",
WARN = "warn",
ERROR = "error",
DEBUG = "debug"
}Type-safe configuration interfaces for bridges, accessories, platforms, and server options.
interface BridgeConfiguration {
name: string;
username: string;
pin: string;
advertiser?: MDNSAdvertiser;
port?: number;
bind?: string | string[];
setupID?: string;
manufacturer?: string;
model?: string;
disableIpc?: boolean;
firmwareRevision?: string;
serialNumber?: string;
}
interface AccessoryConfig extends Record<string, any> {
accessory: string;
name: string;
uuid_base?: string;
_bridge?: BridgeConfiguration;
}
interface PlatformConfig extends Record<string, any> {
platform: string;
name?: string;
_bridge?: BridgeConfiguration;
}Complete re-export of Apple's HomeKit Accessory Protocol implementation, providing all HomeKit services, characteristics, controllers, and utilities.
type HAP = typeof import("hap-nodejs");
// Direct exports of const enums
export {
Categories, Service, Characteristic,
AccessoryEventTypes, ServiceEventTypes, CharacteristicEventTypes,
Formats, Perms, Units, HAPStatus
} from "hap-nodejs";
// Type-only exports of classes and interfaces
export type {
AccessControlManagement, CameraController, AdaptiveLightingController,
DataStreamConnection, StreamController, RemoteController
} from "hap-nodejs";type PluginIdentifier = PluginName | ScopedPluginName;
type PluginName = string;
type ScopedPluginName = string;
type AccessoryName = string;
type PlatformName = string;
type AccessoryIdentifier = string; // format: "PluginIdentifier.AccessoryName"
type PlatformIdentifier = string; // format: "PluginIdentifier.PlatformName"
type UnknownContext = Record<string, any>;
interface HomebridgeConfig {
bridge: BridgeConfiguration;
mdns?: MDNSOptions; // deprecated
accessories: AccessoryConfig[];
platforms: PlatformConfig[];
plugins?: string[];
disabledPlugins?: string[];
ports?: ExternalPortsConfiguration;
}
interface HomebridgeOptions {
keepOrphanedCachedAccessories?: boolean;
hideQRCode?: boolean;
insecureAccess?: boolean;
customPluginPath?: string;
noLogTimestamps?: boolean;
debugModeEnabled?: boolean;
forceColourLogging?: boolean;
customStoragePath?: string;
strictPluginResolution?: boolean;
}
class User {
static configPath(): string;
static persistPath(): string;
static cachedAccessoryPath(): string;
static storagePath(): string;
static setStoragePath(...storagePathSegments: string[]): void;
}