platform.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service, Characteristic } from 'homebridge'
  2. import { PLATFORM_NAME, PLUGIN_NAME } from './settings'
  3. import { accessory } from './accessory'
  4. import { device } from './device'
  5. import { klikAanKlikUitAccessory } from './klikAanKlikUitAccessory'
  6. import { powerSocketAccessory } from './powerSocketAccessory'
  7. import { powerSwitchAccessory } from './powerSwitchAccessory'
  8. import { environmentSensorAccessory } from './environmentSensorAccessory'
  9. import { doorWindowSensorAccessory } from './doorWindowSensorAccessory'
  10. import { motionSensorAccessory } from './motionSensorAccessory'
  11. import { httpServer } from './httpServer'
  12. export class domoticaPlatform implements DynamicPlatformPlugin {
  13. public readonly Service: typeof Service = this.api.hap.Service
  14. public readonly Characteristic: typeof Characteristic = this.api.hap.Characteristic
  15. public readonly accessories: accessory[] = []
  16. public readonly cachedAccessories: PlatformAccessory[] = []
  17. public readonly presentAccessories: PlatformAccessory[] = []
  18. private readonly discoveries: String[] = []
  19. private readonly completedDiscoveries: String[] = []
  20. private httpServer: httpServer = new httpServer(this, this.config)
  21. constructor(
  22. public readonly log: Logger,
  23. public readonly config: PlatformConfig,
  24. public readonly api: API
  25. ) {
  26. this.api.on('didFinishLaunching', () => {
  27. this.discoverDevices()
  28. this.httpServer.start()
  29. })
  30. }
  31. configureAccessory(accessory: PlatformAccessory) {
  32. this.cachedAccessories.push(accessory)
  33. }
  34. discoverDevices() {
  35. this.discoveryStarted('klikAanKlikUitAccessory')
  36. klikAanKlikUitAccessory.discoverDevices(this)
  37. .then((devices) => {
  38. this.processDiscoveredDevices(devices)
  39. this.discoveryCompleted('klikAanKlikUitAccessory')
  40. })
  41. .catch((error) => {
  42. this.log.debug('klikAanKlikUitAccessory.discoverDevices Error ->' + error)
  43. })
  44. this.discoveryStarted('powerSocketAccessory')
  45. powerSocketAccessory.discoverDevices(this)
  46. .then((devices) => {
  47. this.processDiscoveredDevices(devices)
  48. this.discoveryCompleted('powerSocketAccessory')
  49. })
  50. .catch((error) => {
  51. this.log.debug('powerSocketAccessory.discoverDevices Error ->' + error)
  52. })
  53. this.discoveryStarted('powerSwitchAccessory')
  54. powerSwitchAccessory.discoverDevices(this)
  55. .then((devices) => {
  56. this.processDiscoveredDevices(devices)
  57. this.discoveryCompleted('powerSwitchAccessory')
  58. })
  59. .catch((error) => {
  60. this.log.debug('powerSwitchAccessory.discoverDevices Error ->' + error)
  61. })
  62. this.discoveryStarted('environmentSensorAccessory')
  63. environmentSensorAccessory.discoverDevices(this)
  64. .then((devices) => {
  65. this.processDiscoveredDevices(devices)
  66. this.discoveryCompleted('environmentSensorAccessory')
  67. })
  68. .catch((error) => {
  69. this.log.debug('environmentSensorAccessory.discoverDevices Error ->' + error)
  70. })
  71. this.discoveryStarted('doorWindowSensorAccessory')
  72. doorWindowSensorAccessory.discoverDevices(this)
  73. .then((devices) => {
  74. this.processDiscoveredDevices(devices)
  75. this.discoveryCompleted('doorWindowSensorAccessory')
  76. })
  77. .catch((error) => {
  78. this.log.debug('doorWindowSensorAccessory.discoverDevices Error ->' + error)
  79. })
  80. this.discoveryStarted('motionSensorAccessory')
  81. motionSensorAccessory.discoverDevices(this)
  82. .then((devices) => {
  83. this.processDiscoveredDevices(devices)
  84. this.discoveryCompleted('motionSensorAccessory')
  85. })
  86. .catch((error) => {
  87. this.log.debug('motionSensorAccessory.discoverDevices Error ->' + error)
  88. })
  89. }
  90. processDiscoveredDevices(domoticaDevices: device[]) {
  91. for (const device of domoticaDevices) {
  92. const uuid = this.api.hap.uuid.generate(device.uniqueId)
  93. const existingAccessory = this.cachedAccessories.find(accessory => accessory.UUID === uuid)
  94. if (existingAccessory) {
  95. this.log.info('| ' + existingAccessory.context.device.type + ': ' + existingAccessory.displayName)
  96. this.presentAccessories.push(existingAccessory)
  97. if (existingAccessory.displayName != device.deviceName) {
  98. this.log.info('! ' + existingAccessory.displayName + ' => ' + device.deviceName)
  99. existingAccessory.context.device = device
  100. this.api.updatePlatformAccessories([existingAccessory])
  101. }
  102. if (existingAccessory.context.device.type == 'KlikAanKlikUit') {
  103. this.accessories.push(new klikAanKlikUitAccessory(this, existingAccessory))
  104. } else if (existingAccessory.context.device.type == 'PowerSocket') {
  105. this.accessories.push(new powerSocketAccessory(this, existingAccessory))
  106. } else if (existingAccessory.context.device.type == 'PowerSwitch') {
  107. this.accessories.push(new powerSwitchAccessory(this, existingAccessory))
  108. } else if (existingAccessory.context.device.type == 'EnvironmentSensor') {
  109. this.accessories.push(new environmentSensorAccessory(this, existingAccessory))
  110. } else if (existingAccessory.context.device.type == 'DoorWindowSensor') {
  111. this.accessories.push(new doorWindowSensorAccessory(this, existingAccessory))
  112. } else if (existingAccessory.context.device.type == 'MotionSensor') {
  113. this.accessories.push(new motionSensorAccessory(this, existingAccessory))
  114. }
  115. } else {
  116. this.log.info('+ ' + device.type + ': ' + device.deviceName)
  117. const accessory = new this.api.platformAccessory(device.deviceName, uuid)
  118. accessory.context.device = device
  119. if (accessory.context.device.type == 'KlikAanKlikUit') {
  120. this.accessories.push(new klikAanKlikUitAccessory(this, accessory))
  121. } else if (accessory.context.device.type == 'PowerSocket') {
  122. this.accessories.push(new powerSocketAccessory(this, accessory))
  123. } else if (accessory.context.device.type == 'PowerSwitch') {
  124. this.accessories.push(new powerSwitchAccessory(this, accessory))
  125. } else if (accessory.context.device.type == 'EnvironmentSensor') {
  126. this.accessories.push(new environmentSensorAccessory(this, accessory))
  127. } else if (accessory.context.device.type == 'DoorWindowSensor') {
  128. this.accessories.push(new doorWindowSensorAccessory(this, accessory))
  129. } else if (accessory.context.device.type == 'MotionSensor') {
  130. this.accessories.push(new motionSensorAccessory(this, accessory))
  131. }
  132. this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory])
  133. }
  134. }
  135. }
  136. discoveryStarted(deviceType) {
  137. this.discoveries.push(deviceType)
  138. }
  139. discoveryCompleted(deviceType) {
  140. this.completedDiscoveries.push(deviceType)
  141. if (this.completedDiscoveries.length == this.discoveries.length) {
  142. this.cleanupRemovedDevices()
  143. }
  144. //setInterval(this.updateAccessories.bind(this), 60 * 1000); // Poll every minute
  145. }
  146. updateAccessories() {
  147. for (const accessory of this.accessories) {
  148. accessory.update()
  149. }
  150. }
  151. cleanupRemovedDevices() {
  152. for (const existingAccessory of this.cachedAccessories) {
  153. const presentAccessory = this.presentAccessories.find(accessory => accessory.UUID === existingAccessory.UUID)
  154. if (!presentAccessory) {
  155. this.log.info('- ' + existingAccessory.context.device.type + ': ' + existingAccessory.displayName)
  156. this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory])
  157. }
  158. }
  159. }
  160. }