homebridge-switchbot-smartlock
Version:
A Homebridge plugin for controlling SwitchBot Smart Lock via the SwitchBot Cloud API.
124 lines (98 loc) • 5.34 kB
JavaScript
'use strict';
const { SwitchBotSmartLockAccessory } = require('./accessory');
class SwitchBotSmartLockPlatform {
constructor(log, config, api) {
this.log = log;
this.config = config;
this.api = api;
this.accessories = [];
this.lockAccessories = new Map(); // Store accessory instances separately
// Wait for Homebridge to finish launching before adding accessories
api.on('didFinishLaunching', () => {
this.discoverDevices();
});
}
// Required method - called when Homebridge restores cached accessories
configureAccessory(accessory) {
this.log.info('Loading accessory from cache:', accessory.displayName);
// Update the accessory context with current config
accessory.context.config = this.config;
// Update accessory name if it has changed
const newName = this.config.accessoryName || 'Smart Lock';
if (accessory.displayName !== newName) {
this.log.info(`Updating accessory name from "${accessory.displayName}" to "${newName}"`);
accessory.displayName = newName;
accessory._associatedHAPAccessory.displayName = newName;
// Update the platform accessories to reflect the name change
this.api.updatePlatformAccessories([accessory]);
}
// Initialize the accessory and store reference separately (not in context)
const lockAccessory = new SwitchBotSmartLockAccessory(this, accessory);
this.lockAccessories.set(accessory.UUID, lockAccessory);
this.accessories.push(accessory);
}
discoverDevices() {
// Check if we already have this accessory
const uuid = this.api.hap.uuid.generate('switchbot-smartlock-' + this.config.deviceId);
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
if (existingAccessory) {
// Update existing accessory
const newName = this.config.accessoryName || 'Smart Lock';
this.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);
// Update name if changed
if (existingAccessory.displayName !== newName) {
this.log.info(`Updating accessory name from "${existingAccessory.displayName}" to "${newName}"`);
existingAccessory.displayName = newName;
existingAccessory._associatedHAPAccessory.displayName = newName;
// Update the platform accessories to reflect the name change
this.api.updatePlatformAccessories([existingAccessory]);
}
existingAccessory.context.config = this.config;
// FIXED: Check if we already have a lock accessory instance for this UUID
if (!this.lockAccessories.has(existingAccessory.UUID)) {
this.log.info('Creating lock accessory instance for existing accessory');
const lockAccessory = new SwitchBotSmartLockAccessory(this, existingAccessory);
this.lockAccessories.set(existingAccessory.UUID, lockAccessory);
} else {
this.log.info('Lock accessory instance already exists for this accessory');
}
} else {
// Create new accessory
this.log.info('Adding new accessory:', this.config.accessoryName || 'Smart Lock');
this.addAccessory();
}
}
addAccessory() {
const uuid = this.api.hap.uuid.generate('switchbot-smartlock-' + this.config.deviceId);
const accessoryName = this.config.accessoryName || 'Smart Lock';
const accessory = new this.api.platformAccessory(accessoryName, uuid);
// Set accessory information
accessory.getService(this.api.hap.Service.AccessoryInformation)
.setCharacteristic(this.api.hap.Characteristic.Manufacturer, 'SwitchBot')
.setCharacteristic(this.api.hap.Characteristic.Model, 'Smart Lock')
.setCharacteristic(this.api.hap.Characteristic.SerialNumber, this.config.deviceId);
// Only store simple config data in context (no circular references)
accessory.context.config = this.config;
// Store accessory instance separately
const lockAccessory = new SwitchBotSmartLockAccessory(this, accessory);
this.lockAccessories.set(accessory.UUID, lockAccessory);
this.api.registerPlatformAccessories('homebridge-switchbot-smartlock', 'SwitchBotSmartLock', [accessory]);
this.accessories.push(accessory);
}
removeAccessory(accessory) {
this.log.info('Removing accessory:', accessory.displayName);
// Call destroy method if the accessory instance exists
const lockAccessory = this.lockAccessories.get(accessory.UUID);
if (lockAccessory && lockAccessory.destroy) {
lockAccessory.destroy();
}
// Remove from our tracking
this.lockAccessories.delete(accessory.UUID);
this.api.unregisterPlatformAccessories('homebridge-switchbot-smartlock', 'SwitchBotSmartLock', [accessory]);
const index = this.accessories.indexOf(accessory);
if (index > -1) {
this.accessories.splice(index, 1);
}
}
}
module.exports = { SwitchBotSmartLockPlatform };