import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service, Characteristic } from 'homebridge' import { PLATFORM_NAME, PLUGIN_NAME } from './settings' import { accessory } from './accessory' import { device } from './device' import { klikAanKlikUitAccessory } from './klikAanKlikUitAccessory' import { powerSocketAccessory } from './powerSocketAccessory' import { powerSwitchAccessory } from './powerSwitchAccessory' import { environmentSensorAccessory } from './environmentSensorAccessory' import { doorWindowSensorAccessory } from './doorWindowSensorAccessory' import { motionSensorAccessory } from './motionSensorAccessory' import { cameraAccessory } from './cameraAccessory' import { activityAccessory } from './activityAccessory' import { httpServer } from './httpServer' export class domoticaPlatform implements DynamicPlatformPlugin { public readonly Service: typeof Service = this.api.hap.Service public readonly Characteristic: typeof Characteristic = this.api.hap.Characteristic public readonly accessories: accessory[] = [] public readonly cachedAccessories: PlatformAccessory[] = [] public readonly presentAccessories: PlatformAccessory[] = [] private readonly discoveries: String[] = [] private readonly completedDiscoveries: String[] = [] private httpServer: httpServer = new httpServer(this, this.config) constructor( public readonly log: Logger, public readonly config: PlatformConfig, public readonly api: API ) { this.api.on('didFinishLaunching', () => { this.discoverDevices() this.httpServer.start() }) } configureAccessory(accessory: PlatformAccessory) { this.cachedAccessories.push(accessory) } discoverDevices() { this.discoveryStarted('klikAanKlikUitAccessory') klikAanKlikUitAccessory.discoverDevices(this) .then((devices) => { this.processDiscoveredDevices(devices) this.discoveryCompleted('klikAanKlikUitAccessory') }) .catch((error) => { this.log.debug('klikAanKlikUitAccessory.discoverDevices Error ->' + error) }) this.discoveryStarted('powerSocketAccessory') powerSocketAccessory.discoverDevices(this) .then((devices) => { this.processDiscoveredDevices(devices) this.discoveryCompleted('powerSocketAccessory') }) .catch((error) => { this.log.debug('powerSocketAccessory.discoverDevices Error ->' + error) }) this.discoveryStarted('powerSwitchAccessory') powerSwitchAccessory.discoverDevices(this) .then((devices) => { this.processDiscoveredDevices(devices) this.discoveryCompleted('powerSwitchAccessory') }) .catch((error) => { this.log.debug('powerSwitchAccessory.discoverDevices Error ->' + error) }) this.discoveryStarted('environmentSensorAccessory') environmentSensorAccessory.discoverDevices(this) .then((devices) => { this.processDiscoveredDevices(devices) this.discoveryCompleted('environmentSensorAccessory') }) .catch((error) => { this.log.debug('environmentSensorAccessory.discoverDevices Error ->' + error) }) this.discoveryStarted('doorWindowSensorAccessory') doorWindowSensorAccessory.discoverDevices(this) .then((devices) => { this.processDiscoveredDevices(devices) this.discoveryCompleted('doorWindowSensorAccessory') }) .catch((error) => { this.log.debug('doorWindowSensorAccessory.discoverDevices Error ->' + error) }) this.discoveryStarted('motionSensorAccessory') motionSensorAccessory.discoverDevices(this) .then((devices) => { this.processDiscoveredDevices(devices) this.discoveryCompleted('motionSensorAccessory') }) .catch((error) => { this.log.debug('motionSensorAccessory.discoverDevices Error ->' + error) }) this.discoveryStarted('cameraAccessory') cameraAccessory.discoverDevices(this) .then((devices) => { this.processDiscoveredDevices(devices) this.discoveryCompleted('cameraAccessory') }) .catch((error) => { this.log.debug('cameraAccessory.discoverDevices Error ->' + error) }) this.discoveryStarted('activityAccessory') activityAccessory.discoverDevices(this) .then((devices) => { this.processDiscoveredDevices(devices) this.discoveryCompleted('activityAccessory') }) .catch((error) => { this.log.debug('activityAccessory.discoverDevices Error ->' + error) }) } processDiscoveredDevices(domoticaDevices: device[]) { for (const device of domoticaDevices) { const uuid = this.api.hap.uuid.generate(device.uniqueId) const existingAccessory = this.cachedAccessories.find(accessory => accessory.UUID === uuid) if (existingAccessory) { this.log.info('| ' + existingAccessory.context.device.type + ': ' + existingAccessory.displayName) this.presentAccessories.push(existingAccessory) if (existingAccessory.displayName != device.deviceName) { this.log.info('! ' + existingAccessory.displayName + ' => ' + device.deviceName) existingAccessory.context.device = device this.api.updatePlatformAccessories([existingAccessory]) } if (existingAccessory.context.device.type == 'KlikAanKlikUit') { this.accessories.push(new klikAanKlikUitAccessory(this, existingAccessory)) } else if (existingAccessory.context.device.type == 'PowerSocket') { this.accessories.push(new powerSocketAccessory(this, existingAccessory)) } else if (existingAccessory.context.device.type == 'PowerSwitch') { this.accessories.push(new powerSwitchAccessory(this, existingAccessory)) } else if (existingAccessory.context.device.type == 'EnvironmentSensor') { this.accessories.push(new environmentSensorAccessory(this, existingAccessory)) } else if (existingAccessory.context.device.type == 'DoorWindowSensor') { this.accessories.push(new doorWindowSensorAccessory(this, existingAccessory)) } else if (existingAccessory.context.device.type == 'MotionSensor') { this.accessories.push(new motionSensorAccessory(this, existingAccessory)) } else if (existingAccessory.context.device.type == 'Camera') { this.accessories.push(new cameraAccessory(this, existingAccessory)) } else if (existingAccessory.context.device.type == 'Activity') { this.accessories.push(new activityAccessory(this, existingAccessory)) } } else { this.log.info('+ ' + device.type + ': ' + device.deviceName) const accessory = new this.api.platformAccessory(device.deviceName, uuid) accessory.context.device = device if (accessory.context.device.type == 'KlikAanKlikUit') { this.accessories.push(new klikAanKlikUitAccessory(this, accessory)) } else if (accessory.context.device.type == 'PowerSocket') { this.accessories.push(new powerSocketAccessory(this, accessory)) } else if (accessory.context.device.type == 'PowerSwitch') { this.accessories.push(new powerSwitchAccessory(this, accessory)) } else if (accessory.context.device.type == 'EnvironmentSensor') { this.accessories.push(new environmentSensorAccessory(this, accessory)) } else if (accessory.context.device.type == 'DoorWindowSensor') { this.accessories.push(new doorWindowSensorAccessory(this, accessory)) } else if (accessory.context.device.type == 'MotionSensor') { this.accessories.push(new motionSensorAccessory(this, accessory)) } else if (accessory.context.device.type == 'Camera') { this.accessories.push(new cameraAccessory(this, accessory)) } else if (accessory.context.device.type == 'Activity') { this.accessories.push(new activityAccessory(this, accessory)) } this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]) } } } discoveryStarted(deviceType) { this.discoveries.push(deviceType) } discoveryCompleted(deviceType) { this.completedDiscoveries.push(deviceType) if (this.completedDiscoveries.length == this.discoveries.length) { this.cleanupRemovedDevices() } //setInterval(this.updateAccessories.bind(this), 60 * 1000); // Poll every minute } updateAccessories() { for (const accessory of this.accessories) { accessory.update() } } cleanupRemovedDevices() { for (const existingAccessory of this.cachedAccessories) { const presentAccessory = this.presentAccessories.find(accessory => accessory.UUID === existingAccessory.UUID) if (!presentAccessory) { this.log.info('- ' + existingAccessory.context.device.type + ': ' + existingAccessory.displayName) this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]) } } } }