UNPKG

homebridge-framework

Version:
214 lines (183 loc) 7.71 kB
import { PlatformAccessory } from 'homebridge'; import { HomebridgePlatform } from './homebridge-platform'; import { Service } from './service'; import { Categories as Category, Service as HapService } from 'hap-nodejs'; import { AccessoryInformation } from './accessory-information'; /** * Represents a wrapper around HAP accessories with with support for auto-removal of unused services. */ export class Accessory { /** * Initializes a new Accessory instance. * @param platform The homebridge platform. * @param name The name that should be displayed in HomeKit. * @param id The identifier of the accessory. * @param subType The sub type of the accessory. May be omitted if the ID is already unique. * @param category The category of the accessory, which determines the icon in the Apple Home app. * @param isExternal Determines whether the accessory is an external accessory (in contrast to bridged accessories). */ constructor(platform: HomebridgePlatform<any>, name: string, id: string, subType?: string, category?: Category, isExternal?: boolean) { this._platform = platform; this._name = name; this._id = id; this._subType = subType || null; this._isExternal = isExternal || false; // Checks if the accessory has been cached if (!this.isExternal) { const platformAccessory = this.platform.cachedPlatformAccessories.find(a => a.context.id === id && a.context.subType === (subType || null)); if (platformAccessory) { this._platformAccessory = platformAccessory; return; } } // Creates the new accessory this._platformAccessory = new this.platform.api.platformAccessory(name, this.platform.api.hap.uuid.generate(this.uniqueId), category) as PlatformAccessory; this.platformAccessory.context.id = id; this.platformAccessory.context.subType = (subType || null); // Registers the accessory if (!this.isExternal) { this.platform.api.registerPlatformAccessories(this.platform.pluginName, this.platform.platformName, [this.platformAccessory]); } } /** * Contains the parent platform. */ private _platform: HomebridgePlatform<any>; /** * Gets the parent platform. * @internal */ public get platform(): HomebridgePlatform<any> { return this._platform; } /** * Contains the platform accessory. */ private _platformAccessory: PlatformAccessory; /** * Gets the platform accessory. * @internal */ public get platformAccessory(): PlatformAccessory { return this._platformAccessory; } /** * Contains the name that should be displayed in HomeKit. */ private _name: string; /** * Gets the name that should be displayed in HomeKit. */ public get name(): string { return this._name; } /** * Contains the identifier of the accessory. Is unique in combination with the sub type. */ private _id: string; /** * Gets the identifier of the accessory. Is unique in combination with the sub type. */ public get id(): string { return this._id; } /** * Contains the sub type of the accessory. Is unique in combination with the ID. */ private _subType: string|null; /** * Gets the sub type of the accessory. Is unique in combination with the ID. */ public get subType(): string|null { return this._subType; } /** * Contains a value that determines whether the accessory is an external accessory (in contrast to bridged accessories). */ private _isExternal: boolean = false; /** * Gets a value that determines whether the accessory is an external accessory (in contrast to bridged accessories). */ public get isExternal(): boolean { return this._isExternal; } /** * Gets the unique identifier of the accessory, which is made up from the ID and the sub type. */ public get uniqueId(): string { return `${this.id}-${(this.subType || '')}`; } /** * Updates the accessory information service. * @param information The accessory information. */ public setInformation(information: AccessoryInformation) { // Makes sure the accessory information service is used const accessoryInformationService = this.useService(this.platform.api.hap.Service.AccessoryInformation, this.name); // Updates the information characteristics if (information.manufacturer != null) { accessoryInformationService.useCharacteristic(this.platform.api.hap.Characteristic.Manufacturer, information.manufacturer); } if (information.model != null) { accessoryInformationService.useCharacteristic(this.platform.api.hap.Characteristic.Model, information.model); } if (information.serialNumber != null) { accessoryInformationService.useCharacteristic(this.platform.api.hap.Characteristic.SerialNumber, information.serialNumber); } if (information.firmwareRevision != null) { accessoryInformationService.useCharacteristic(this.platform.api.hap.Characteristic.FirmwareRevision, information.firmwareRevision); } if (information.hardwareRevision != null) { accessoryInformationService.useCharacteristic(this.platform.api.hap.Characteristic.HardwareRevision, information.hardwareRevision); } } /** * Contains the services. */ private _services: Array<Service> = new Array<Service>(); /** * Gets the services. */ public get services(): Array<Service> { return this._services; } /** * Defines a service for usage with the accessory. When defining a service, it is marked as used and thus not removed from HomeKit after the initialization. * @param type The type of the service. * @param name The name that should be displayed in HomeKit. * @param subType The sub type of the service. May be omitted if the type is already unique. */ public useService(type: typeof HapService, name: string, subType?: string): Service { // Checks if the service has already been defined for usage let service = this.services.find(s => s.type === type && s.subType === (subType || null)); if (service) { return service; } // Creates a new service and returns it service = new Service(this, type, name, subType); this.services.push(service); return service; } /** * Removes all cached services that have not been defined for usage. */ public removeUnusedServices() { const services = this.platformAccessory.services.slice(); for (let service of services) { // The accessory information service is always required if (service.UUID === this.platform.api.hap.Service.AccessoryInformation.UUID) { continue; } // Removes the unused services if (service.subtype) { if (!this.services.some(d => service.UUID === d.hapService.UUID && service.subtype === d.hapService.subtype)) { this.platformAccessory.removeService(service); } } else { if (!this.services.some(d => service.UUID === d.hapService.UUID && !d.hapService.subtype)) { this.platformAccessory.removeService(service); } } } } }