UNPKG

@homebridge-plugins/homebridge-resideo

Version:

The Resideo plugin allows you to access your Resideo device(s) from HomeKit.

125 lines 6.36 kB
import { ResideoPlatform } from './Platform.HAP.js'; import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'; /** * ResideoMatterPlatform * Extends ResideoPlatform with Homebridge Matter support (Homebridge v2.0+). * When Matter is available and enabled the platform registers Resideo devices * as Matter accessories; otherwise it falls back to the standard HAP path * inherited from ResideoPlatform. */ export class ResideoMatterPlatform extends ResideoPlatform { /** * Map of cached Matter accessories restored from disk at startup. * Keyed by UUID so duplicates are avoided on re-launch. */ matterAccessories = new Map(); constructor(log, config, api) { super(log, config, api); } /** * Delegates to the base-class implementation so the HAP accessories array * (`this.accessories`) is always populated. This is required for the HAP * fallback path inside `discoverDevices` to work correctly and prevents * duplicate HAP accessories from being created on re-launch. * * When Matter mode is active those HAP accessories will be unregistered at * the start of `discoverDevices`, cleanly migrating away from legacy HAP. */ configureAccessory(accessory) { super.configureAccessory(accessory); } /** * Called by Homebridge when a cached Matter accessory is restored from disk. */ configureMatterAccessory(accessory) { this.debugLog(`Loading cached Matter accessory: ${accessory.displayName}`); this.matterAccessories.set(accessory.UUID, accessory); } /** * Returns true when the running Homebridge instance has Matter available * and the user has Matter enabled (both bridge-level and plugin-level). */ get matterActive() { const iface = this.api; return !!(iface?.isMatterAvailable?.() && iface?.isMatterEnabled?.()); } /** * Overrides ResideoPlatform.discoverDevices. * * When Matter is active all discovered Resideo devices are registered as * Matter accessories via `api.matter.registerPlatformAccessories`. * Any previously cached HAP accessories are unregistered first to avoid * leaving stale HAP accessories when transitioning to Matter. * * When Matter is not active the call is delegated to the parent HAP * implementation so the plugin continues to work with Homebridge v1.x. */ async discoverDevices() { if (!this.matterActive) { this.debugLog('Matter is not available or not enabled – falling back to HAP device discovery.'); return super.discoverDevices(); } this.infoLog('Matter is available and enabled – registering Resideo devices as Matter accessories.'); // Unregister any legacy HAP accessories that were restored from cache so // they don't remain as duplicate/stale entries alongside Matter accessories. if (this.accessories.length > 0) { this.debugLog(`Removing ${this.accessories.length} cached HAP accessory(s) before switching to Matter.`); for (const hapAccessory of this.accessories) { this.unregisterPlatformAccessories(hapAccessory); } this.accessories.length = 0; } try { const locations = await this.discoverlocations() ?? []; this.infoLog(`Total Locations Found: ${locations.length}`); if (locations.length === 0) { this.debugLog('No locations found.'); return; } const matterApi = this.api.matter; const accessories = []; for (const location of locations) { this.infoLog(`Total Devices Found at ${location.name}: ${location.devices.length}`); const deviceLists = location.devices; const configDevices = this.config.options?.devices; const devices = configDevices ? this.mergeByDeviceID(deviceLists.map((device) => ({ ...device, deviceID: String(device.deviceID).trim() })), configDevices.map((device) => ({ ...device, deviceID: String(device.deviceID).trim() }))) : deviceLists.slice(); for (const device of devices) { if (device.hide_device) { this.debugLog(`Skipping hidden device: ${device.userDefinedDeviceName}`); continue; } const uuid = matterApi.uuid.generate(`${device.deviceID}-${device.deviceClass}`); const displayName = device.configDeviceName ?? device.userDefinedDeviceName ?? `${device.deviceClass} ${device.deviceID}`; const existingAccessory = this.matterAccessories.get(uuid); if (existingAccessory) { this.infoLog(`Restoring existing Matter accessory from cache: ${existingAccessory.displayName}`); existingAccessory.context.device = device; existingAccessory.context.location = location; await matterApi.updatePlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]); this.matterAccessories.set(uuid, existingAccessory); } else { this.debugLog(`Creating new Matter accessory for: ${displayName} (${device.deviceClass})`); const MatterAccessory = this.api.matterAccessory; const accessory = new MatterAccessory(displayName, uuid); accessory.context.device = device; accessory.context.location = location; accessories.push(accessory); this.matterAccessories.set(uuid, accessory); } } } if (accessories.length > 0) { this.infoLog(`Registering ${accessories.length} new Matter accessory(s).`); await matterApi.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, accessories); } } catch (e) { this.action = 'Discover Devices (Matter)'; this.apiError(e); } } } //# sourceMappingURL=Platform.Matter.js.map