|
|
@@ -0,0 +1,189 @@
|
|
|
+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 { 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)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 {
|
|
|
+ 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))
|
|
|
+ }
|
|
|
+
|
|
|
+ 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])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|