diff --git a/ChangeLog.md b/ChangeLog.md index 3f75d77..bdd0f72 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,7 +1,8 @@ # 1.4.3 # -## Brightness of Lightbulb is now optional ## +## Added multi accessory ## +## Brightness of Lightbulb is now optional ## # 1.4.2 # diff --git a/Logger/IMG_0001.PNG b/Logger/IMG_0001.PNG deleted file mode 100644 index 2d4aff2..0000000 Binary files a/Logger/IMG_0001.PNG and /dev/null differ diff --git a/Logger/IMG_0002.PNG b/Logger/IMG_0002.PNG deleted file mode 100644 index 667b030..0000000 Binary files a/Logger/IMG_0002.PNG and /dev/null differ diff --git a/Logger/IMG_0003.PNG b/Logger/IMG_0003.PNG deleted file mode 100644 index d72307d..0000000 Binary files a/Logger/IMG_0003.PNG and /dev/null differ diff --git a/Logger/IMG_0004.PNG b/Logger/IMG_0004.PNG deleted file mode 100644 index 0aa0dd9..0000000 Binary files a/Logger/IMG_0004.PNG and /dev/null differ diff --git a/Logger/IMG_0005.PNG b/Logger/IMG_0005.PNG deleted file mode 100644 index 1d7b601..0000000 Binary files a/Logger/IMG_0005.PNG and /dev/null differ diff --git a/Logger/IMG_0006.PNG b/Logger/IMG_0006.PNG deleted file mode 100644 index 5cf985e..0000000 Binary files a/Logger/IMG_0006.PNG and /dev/null differ diff --git a/Logger/IMG_0007.PNG b/Logger/IMG_0007.PNG deleted file mode 100644 index fada6d5..0000000 Binary files a/Logger/IMG_0007.PNG and /dev/null differ diff --git a/Logger/IMG_0008.PNG b/Logger/IMG_0008.PNG deleted file mode 100644 index e450fa5..0000000 Binary files a/Logger/IMG_0008.PNG and /dev/null differ diff --git a/Logger/README.md b/Logger/README.md deleted file mode 100644 index 713d4bf..0000000 --- a/Logger/README.md +++ /dev/null @@ -1,13 +0,0 @@ -### Test for creating a switch accessory with an additional switch sub-accessory, for example to switch the logger for the main accessory on and off. - -007 -008 - -003 -004 - -002 -006 - -001 -005 diff --git a/Logger/logSwitchPlatformAccessory.ts b/Logger/logSwitchPlatformAccessory.ts deleted file mode 100644 index 6b3b7f0..0000000 --- a/Logger/logSwitchPlatformAccessory.ts +++ /dev/null @@ -1,76 +0,0 @@ -// each service must implement at-minimum the "required characteristics" for the given service type -// see https://developers.homebridge.io/#/service/Lightbulb - -import { AccessoryPlugin, API, Service, CharacteristicValue } from 'homebridge'; -import { md5 } from "../md5"; - -export class LogSwitchPlatformAccessory implements AccessoryPlugin { - - private model: string = "Logger Switch"; - - private api: API; - private service: Service; - private information: Service; - - private platform: any; - private device: any; - - private accStates = { - On: false, - }; - - name: string; - - constructor( api: API, platform: any, device: any, parent: any ) { - - this.name = device.name + '-Logger'; - this.api = api; - this.platform = platform; - this.device = device; - - this.service = new this.api.hap.Service.Switch(this.name); - // this.service.setCharacteristic(this.platform.Characteristic.ServiceLabelIndex, '1'); - - this.service.subtype = 'logger'; - - this.service.getCharacteristic(this.api.hap.Characteristic.On) - .onSet(this.setOn.bind(this)) - .onGet(this.getOn.bind(this)); - - this.information = new this.api.hap.Service.AccessoryInformation() - .setCharacteristic(this.api.hap.Characteristic.Manufacturer, this.platform.manufacturer) - .setCharacteristic(this.api.hap.Characteristic.Model, this.model + ' @ ' + this.platform.model) - .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.name + this.model)) - .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); - - parent.service.addLinkedService(this.service); - parent.services.push(this.service); - - } - - getServices(): Service[] { - return [ this.information, this.service ]; - } - - async setOn(value: CharacteristicValue) { - - this.accStates.On = value as boolean; - - if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { - this.platform.log.info('[%s] [%s] Set On <- %s', this.device.name, this.name, value); - } - - } - - async getOn(): Promise { - - const isOn = this.accStates.On; - - if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { - this.platform.log.info('[%s] [%s] Get On -> %s', this.device.name, this.name, this.accStates.On); - } - - return isOn; - } - -} diff --git a/Logger/switchPlatformAccessory.ts b/Logger/switchPlatformAccessory.ts deleted file mode 100644 index 984796d..0000000 --- a/Logger/switchPlatformAccessory.ts +++ /dev/null @@ -1,179 +0,0 @@ -// each service must implement at-minimum the "required characteristics" for the given service type -// see https://developers.homebridge.io/#/service/Lightbulb - -import { AccessoryPlugin, API, Service, CharacteristicValue } from 'homebridge'; - -import { QueueSendItem, QueueReceiveItem } from "../queue"; -import { ErrorNumber } from "../error"; -import { md5 } from "../md5"; -import { UdpClient } from '../udp'; - -import { LogSwitchPlatformAccessory } from '../logging/logSwitchPlatformAccessory'; // <-- Logger - -export class SwitchPlatformAccessory implements AccessoryPlugin { - - private model: string = "Switch"; - - private api: API; - private service: Service; - private information: Service; - - private platform: any; - private device: any; - private pushButton: number; - private logging: number; - private updateOnQueued: boolean; - - private udpClient: UdpClient; - - private logger: any[]; // <-- Logger - public services: Service[]; // <-- Logger - - private accStates = { - On: false, - }; - - name: string; - - constructor( api: API, platform: any, device: any ) { - - this.name = device.name; - this.api = api; - this.platform = platform; - this.device = device; - this.pushButton = this.device.pushButton || this.platform.pushButton; - this.logging = this.device.logging || 0; - - this.udpClient = new UdpClient(this.platform, this.device); - - this.logger = []; // <-- Logger - this.services = []; // <-- Logger - - this.errorCheck(); - - this.service = new this.api.hap.Service.Switch(this.device.name); - - this.service.subtype = 'main'; // <-- Logger - - this.service.getCharacteristic(this.api.hap.Characteristic.On) - .onSet(this.setOn.bind(this)) - .onGet(this.getOn.bind(this)); - - this.information = new this.api.hap.Service.AccessoryInformation() - .setCharacteristic(this.api.hap.Characteristic.Manufacturer, this.platform.manufacturer) - .setCharacteristic(this.api.hap.Characteristic.Model, this.model + ' @ ' + this.platform.model) - .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) - .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); - - this.services.push(this.service, this.information); // <-- Logger - - this.updateOnQueued = false; - - if (this.platform.config.updateInterval) { - - setInterval(() => { - this.updateOn(); - }, this.platform.config.updateInterval); - - } - - // ------------------------------------------------------------------------ - /* im Übergeortneten Accessory: - private valveAccessories: any[]; - public services: Service[]; - this.valveAccessories = []; - const configDevices = this.platform.config.devices; - for (const dev of configDevices) { - this.valveAccessories.push(new ValvePlatformAccessory(api, platform, dev, this)); <-- this == parent !!!! - this.services.push(this.service, this.information); - getServices(): Service[] { - return this.services; - } - } - for (const dev of this.valveAccessories) { - isInUse |= dev.getInUse(); - } - // ------------------------------------------------------------------------ - /* im untergeortneten Accessory: - this.service = new this.api.hap.Service.Valve(this.device.name, this.device.valveZone); <-- geht eventuel nur bei Valve !?! - this.service.setCharacteristic(this.platform.Characteristic.ServiceLabelIndex, this.device.valveZone); - parent.service.addLinkedService(this.service); - parent.services.push(this.service); - */ - - // --> Logger - // multiple switches for InfluxDB, Fagato, ... - this.logger.push(new LogSwitchPlatformAccessory(api, platform, device, this)); - - } - - errorCheck() { - if (!this.device.switchGet || !this.device.switchSetOn || !this.device.switchSetOff) { - this.platform.log.error('[%s] One or more LOGO! Addresses are not correct!', this.device.name); - } - } - - getServices(): Service[] { - // return [ this.information, this.service ]; - return this.services; // <-- Logger - } - - async setOn(value: CharacteristicValue) { - - this.accStates.On = value as boolean; - - if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { - this.platform.log.info('[%s] Set On <- %s', this.device.name, value); - } - - let qItem: QueueSendItem; - if (value) { - qItem = new QueueSendItem(this.device.switchSetOn, value as number, this.pushButton); - } else { - qItem = new QueueSendItem(this.device.switchSetOff, value as number, this.pushButton); - } - this.platform.queue.bequeue(qItem); - - } - - async getOn(): Promise { - - const isOn = this.accStates.On; - this.updateOn(); - - return isOn; - } - - updateOn() { - - if (this.updateOnQueued) {return;} - - let qItem: QueueReceiveItem = new QueueReceiveItem(this.device.switchGet, async (value: number) => { - - if (value != ErrorNumber.noData) { - - const on = value == 1 ? true : false; - this.accStates.On = on; - - if (this.platform.config.debugMsgLog || this.device.debugMsgLog) { - this.platform.log.info('[%s] Get On -> %s', this.device.name, this.accStates.On); - } - - this.service.updateCharacteristic(this.api.hap.Characteristic.On, this.accStates.On); - - if (this.logging) { - this.udpClient.sendMessage("On", String(this.accStates.On)); - } - } - - this.updateOnQueued = false; - - }); - - if (this.platform.queue.enqueue(qItem) === 1) { - this.updateOnQueued = true; - }; - - } - -} diff --git a/Logger/test_config.json b/Logger/test_config.json deleted file mode 100644 index 476c1a8..0000000 --- a/Logger/test_config.json +++ /dev/null @@ -1,56 +0,0 @@ -"platforms": [ - { - "platform": "LogoPlatform", - "name": "Logo 6", - "ip": "192.168.1.167", - "port": 502, - "updateInterval": 10000, - "debugMsgLog": 0, - "pushButton": 1, - "devices": [ - { - "name": "Q1-A", - "type": "switch", - "switchGet": "Q1", - "switchSetOn": "V1.0", - "switchSetOff": "V1.1", - "logging": 1 - }, - { - "name": "Q1-B", - "type": "switch", - "switchGet": "Q1", - "switchSetOn": "V1.0", - "switchSetOff": "V1.1", - "logging": 1 - }, - { - "name": "Q1-C", - "type": "switch", - "switchGet": "Q1", - "switchSetOn": "V1.0", - "switchSetOff": "V1.1", - "logging": 1 - }, - { - "name": "Q2", - "type": "outlet", - "outletGet": "Q2", - "outletSetOn": "V1.2", - "outletSetOff": "V1.3", - "outletGetInUse": "Q3", - "logging": 1 - }, - { - "name": "Q4", - "type": "lightbulb", - "lightbulbGet": "Q4", - "lightbulbSetOn": "V2.0", - "lightbulbSetOff": "V2.1", - "lightbulbSetBrightness": "VW20", - "lightbulbGetBrightness": "VW22", - "logging": 1 - } - ] - } - ], \ No newline at end of file diff --git a/README.md b/README.md index b7de39a..480324d 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ __Type of Sensor Accessory:__ __Special Functions:__ - [Logging to InfluxDB or Eve App](#logging-to-influxdb-or-eve-app) +- [Multi Accessory](#other-configuration) __Examples:__ @@ -76,35 +77,36 @@ __Examples:__ ## Platform Main Configuration Parameters ## -Name | Value | Required | Notes ------------------ | ------------------------ | ------------- | ------------------------ -`platform` | "LogoPlatform" | yes | Must be set to "LogoPlatform". -`name` | (custom) | yes | Name of platform that will not appear in homekit app. -`interface` | "modbus" or "snap7" | no | Interface for communication, default is: "modbus". -`ip` | "10.0.0.100" | yes | Must be set to the IP of your LOGO!. -`port` | 502 | no (ModBus) | Must be set to the Modbus Port of your LOGO!, default is: 502. -`logoType` | "0BA7" or ... | no (Snap7) | Must be set to the [Type of your LOGO](#type-of-your-logo), default is: "0BA7". -`localTSAP` | "0x1200" | no (Snap7) | Must be set to the local TSAP of your LOGO!, default is: "0x1200". -`remoteTSAP` | "0x2200" | no (Snap7) | Must be set to the remote TSAP of your LOGO!, default is: "0x2200". -`queueInterval` | 100 ... 1000 | no | Interval to send queries from Plugin to LOGO!, in milliseconds, default is: 100. -`queueSize` | 100 ... 1000 | no | Number of items to be hold in send/receive queue, default is: 100. -`updateInterval` | 0 ... ∞ | no | Auto Update Interval in milliseconds, 0 = Off -`debugMsgLog` | 0 or 1 | no | Displays messages of all accessories in the log, default is: 0. -`retryCount` | 0 ... ∞ | no | Retry count for sending the queries messages, default is: 5. -`pushButton` | 0 or 1 | no | If e.g. the network input in the LOGO! a hardware button on the LOGO! simulated, default is: 0. (For all Accessories.) -`loggerType` | "influxDB" or "fakegato" | no | Activates Logging, default is: "none". -`loggerInterval` | 300000 | no | Logging Interval in milliseconds, default is: 300000 (5min) -`influxDBUrl` | "" | no (InfluxDB) | IP-Address and Port for InfluxDB -`influxDBToken` | "API Token", | no (InfluxDB) | InfluxDB API token -`influxDBOrg` | "Org", | no (InfluxDB) | InfluxDB organization ID -`influxDBBucket` | "Bucket", | no (InfluxDB) | InfluxDB bucket name +Name | Value | Required | Notes +----------------- | ------------------------- | ------------- | ------------------------ +`platform` | "LogoPlatform" | yes | Must be set to "LogoPlatform". +`name` | (custom) | yes | Name of platform that will not appear in homekit app. +`interface` | "modbus" or "snap7" | no | Interface for communication, default is: "modbus". +`ip` | "10.0.0.100" | yes | Must be set to the IP of your LOGO!. +`port` | 502 | no (ModBus) | Must be set to the Modbus Port of your LOGO!, default is: 502. +`logoType` | "0BA7" or ... | no (Snap7) | Must be set to the [Type of your LOGO](#type-of-your-logo), default is: "0BA7". +`localTSAP` | "0x1200" | no (Snap7) | Must be set to the local TSAP of your LOGO!, default is: "0x1200". +`remoteTSAP` | "0x2200" | no (Snap7) | Must be set to the remote TSAP of your LOGO!, default is: "0x2200". +`queueInterval` | 100 ... 1000 | no | Interval to send queries from Plugin to LOGO!, in milliseconds, default is: 100. +`queueSize` | 100 ... 1000 | no | Number of items to be hold in send/receive queue, default is: 100. +`updateInterval` | 0 ... ∞ | no | Auto Update Interval in milliseconds, 0 = Off +`debugMsgLog` | 0 or 1 | no | Displays messages of all accessories in the log, default is: 0. +`retryCount` | 0 ... ∞ | no | Retry count for sending the queries messages, default is: 5. +`pushButton` | 0 or 1 | no | If e.g. the network input in the LOGO! a hardware button on the LOGO! simulated, default is: 0. (For all Accessories.) +`loggerType` | "influxDB" or "fakegato" | no | Activates Logging, default is: "none". +`loggerInterval` | 300000 | no | Logging Interval in milliseconds, default is: 300000 (5min) +`influxDBUrl` | "" | no (InfluxDB) | IP-Address and Port for InfluxDB +`influxDBToken` | "API Token" | no (InfluxDB) | InfluxDB API token +`influxDBOrg` | "Org" | no (InfluxDB) | InfluxDB organization ID +`influxDBBucket` | "Bucket" | no (InfluxDB) | InfluxDB bucket name +`parentAccessory` | (custom) | no | Parent accessory name, needed to create this accessory as a sub-accessory of an other accessory. Not for Valve, IrrigationSystem and Other ## Device Main Configuration Parameters ## Name | Value | Required | Notes ------------------------ | ------------------- | -------- | ------------------------ `name` | (custom) | yes | Name of accessory that will appear in homekit app. -`type` | "switch" or ... | yes | Type of Accessory: "switch", "lightbulb", "blind", "window", "garagedoor", "thermostat", "irrigationSystem", "valve", "fan", "fanv2", "filterMaintenance", "outlet" or Type of Sensor Accessory: "lightSensor", "motionSensor", "contactSensor", "smokeSensor", "temperatureSensor", "humiditySensor", "carbonDioxideSensor", "airQualitySensor" +`type` | "switch" or ... | yes | Type of Accessory: "switch", "lightbulb", "blind", "window", "garagedoor", "thermostat", "irrigationSystem", "valve", "fan", "filterMaintenance", "outlet", "other" or Type of Sensor Accessory: "lightSensor", "motionSensor", "contactSensor", "smokeSensor", "temperatureSensor", "humiditySensor", "carbonDioxideSensor", "airQualitySensor" `debugMsgLog` | 0 or 1 | no | Displays messages of this accessory in the log, default is: 0. `pushButton` | 0 or 1 | no | If e.g. the network input in the LOGO! a hardware button on the LOGO! simulated, default is: 0. (Only for this Accessory.) `logging` | 0 or 1 | no | Activates Logging, default is: 0. (Only for this Accessory.) @@ -116,8 +118,9 @@ Name | Value | Required | Notes "name": "Logo 1", "ip": "10.0.0.100", "port": 505, - "debugMsgLog": 1, "updateInterval": 10000, + "debugMsgLog": 1, + "pushButton": 1, "devices": [ { "name": "Accessory Name 1", @@ -139,8 +142,9 @@ Name | Value | Required | Notes "logoType": "0BA8", "localTSAP": "0x4200", "remoteTSAP": "0x4300", - "debugMsgLog": 1, "updateInterval": 10000, + "debugMsgLog": 1, + "pushButton": 1, "devices": [ { "name": "Accessory Name 3", @@ -478,6 +482,63 @@ Name | Value | Required | Option for | Notes } ``` +## Other Configuration ## + +This accessory can contain other accessories, but does not respond to tapping to turn it on or off. +It opens a detailed view of the sub accessories. + +Name | Value | Required | Option for | Notes +------------------------ | ------------------- | -------- | ---------- | ------------------------ +`name` | (custom) | yes | Name of accessory that will appear in homekit app. +`type` | "other" | yes | Type of Accessory: "other" + +```json +{ + "name": "Ventilation", + "type": "other" +}, +{ + "name": "Level 1", + "type": "switch", + "switchGet": "Q3", + "switchSetOn": "V3.2", + "switchSetOff": "V4.2", + "parentAccessory": "Ventilation" +}, +{ + "name": "Level 2", + "type": "switch", + "switchGet": "Q4", + "switchSetOn": "V3.3", + "switchSetOff": "V4.3", + "parentAccessory": "Ventilation" +}, +{ + "name": "Automatic", + "type": "switch", + "switchGet": "M16", + "switchSetOn": "V3.4", + "switchSetOff": "V4.4", + "parentAccessory": "Ventilation" +}, +{ + "name": "Supply Air", + "type": "temperatureSensor", + "convertValue": 1, + "temperature": "AM5", + "parentAccessory": "Ventilation" +}, +{ + "name": "Exhaust Air", + "type": "temperatureSensor", + "convertValue": 1, + "temperature": "AM6", + "parentAccessory": "Ventilation" +} +``` + +other + ## Light Sensor Configuration ## Name | Value | Required | Option for | Notes @@ -655,8 +716,9 @@ Name | Value | Required | Option for | Notes "name": "Logo 6", "ip": "10.0.0.100", "port": 502, + "updateInterval": 10000, "debugMsgLog": 1, - "updateInterval": 30000, + "pushButton": 1, "loggerType": "influxDB", "loggerInterval": 30000, "influxDBUrl": "http://10.0.0.99:8086", @@ -716,6 +778,7 @@ Name | Value | Required | Option for | Notes "remoteTSAP": "0x2100", "updateInterval": 10000, "debugMsgLog": 1, + "pushButton": 1, "retryCount": 5, "devices": [ { diff --git a/other-ventilation.png b/other-ventilation.png new file mode 100644 index 0000000..f8eb4a2 Binary files /dev/null and b/other-ventilation.png differ diff --git a/package-lock.json b/package-lock.json index ce01645..cc18367 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "homebridge-logo-platform", - "version": "1.4.2", + "version": "1.4.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "homebridge-logo-platform", - "version": "1.4.2", + "version": "1.4.3", "license": "---", "dependencies": { "@influxdata/influxdb-client": "^1.33.2", diff --git a/package.json b/package.json index 21380ed..1ddf261 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Homebridge Logo Platform", "name": "homebridge-logo-platform", - "version": "1.4.2", + "version": "1.4.3", "model": "Logo Platform", "description": "This is a Siemens LOGO! Platform Plugin.", "license": "---", diff --git a/src/accessories/blindPlatformAccessory.ts b/src/accessories/blindPlatformAccessory.ts index 5fa098b..3776da0 100644 --- a/src/accessories/blindPlatformAccessory.ts +++ b/src/accessories/blindPlatformAccessory.ts @@ -4,6 +4,26 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { SwitchPlatformAccessory } from './switchPlatformAccessory'; +import { LightbulbPlatformAccessory } from './lightbulbPlatformAccessory'; +import { WindowPlatformAccessory } from './windowPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './garagedoorPlatformAccessory'; +import { ThermostatPlatformAccessory } from './thermostatPlatformAccessory'; +import { FanPlatformAccessory } from './fanPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './filterMaintenancePlatformAccessory'; +import { OutletPlatformAccessory } from './outletPlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; export class BlindPlatformAccessory implements AccessoryPlugin { @@ -13,6 +33,9 @@ export class BlindPlatformAccessory implements AccessoryPlugin { private service: Service; private information: Service; + private subs: any[]; + public services: Service[]; + private platform: any; private device: any; private pushButton: number; @@ -31,8 +54,9 @@ export class BlindPlatformAccessory implements AccessoryPlugin { }; name: string; + isParentAccessory: boolean; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -41,11 +65,20 @@ export class BlindPlatformAccessory implements AccessoryPlugin { this.pushButton = this.device.pushButton || this.platform.pushButton; this.logging = this.device.logging || 0; + this.subs = []; + this.services = []; + + this.isParentAccessory = false; + this.errorCheck(); this.currentPositionIsTargetPositionInLogo = this.checkPosition(); this.service = new this.api.hap.Service.WindowCovering(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.platform.Characteristic.CurrentPosition) .onGet(this.getCurrentPosition.bind(this)); @@ -62,6 +95,98 @@ export class BlindPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } + + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateCurrentPositionAndTargetPositionQueued = false; this.updateCurrentPositionQueued = false; this.updateTargetPositionQueued = false; @@ -102,7 +227,7 @@ export class BlindPlatformAccessory implements AccessoryPlugin { } getServices(): Service[] { - return [ this.information, this.service ]; + return this.services; } async setTargetPosition(value: CharacteristicValue) { diff --git a/src/accessories/fanPlatformAccessory.ts b/src/accessories/fanPlatformAccessory.ts index 5b5a057..4781a1d 100644 --- a/src/accessories/fanPlatformAccessory.ts +++ b/src/accessories/fanPlatformAccessory.ts @@ -4,6 +4,26 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { SwitchPlatformAccessory } from './switchPlatformAccessory'; +import { LightbulbPlatformAccessory } from './lightbulbPlatformAccessory'; +import { BlindPlatformAccessory } from './blindPlatformAccessory'; +import { WindowPlatformAccessory } from './windowPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './garagedoorPlatformAccessory'; +import { ThermostatPlatformAccessory } from './thermostatPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './filterMaintenancePlatformAccessory'; +import { OutletPlatformAccessory } from './outletPlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; export class FanPlatformAccessory implements AccessoryPlugin { @@ -13,6 +33,9 @@ export class FanPlatformAccessory implements AccessoryPlugin { private service: Service; private information: Service; + private subs: any[]; + public services: Service[]; + private platform: any; private device: any; private pushButton: number; @@ -28,8 +51,9 @@ export class FanPlatformAccessory implements AccessoryPlugin { }; name: string; + isParentAccessory: boolean; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -38,10 +62,19 @@ export class FanPlatformAccessory implements AccessoryPlugin { this.pushButton = this.device.pushButton || this.platform.pushButton; this.logging = this.device.logging || 0; + this.subs = []; + this.services = []; + + this.isParentAccessory = false; + this.errorCheck(); this.service = new this.api.hap.Service.Fan(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.platform.Characteristic.On) .onSet(this.setOn.bind(this)) .onGet(this.getOn.bind(this)); @@ -64,6 +97,98 @@ export class FanPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } + + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateOnQueued = false; this.updateRotationDirectionQueued = false; this.updateRotationSpeedQueued = false; @@ -92,7 +217,7 @@ export class FanPlatformAccessory implements AccessoryPlugin { } getServices(): Service[] { - return [ this.information, this.service ]; + return this.services; } async setOn(value: CharacteristicValue) { diff --git a/src/accessories/filterMaintenancePlatformAccessory.ts b/src/accessories/filterMaintenancePlatformAccessory.ts index 24eca4e..5b6dd01 100644 --- a/src/accessories/filterMaintenancePlatformAccessory.ts +++ b/src/accessories/filterMaintenancePlatformAccessory.ts @@ -4,6 +4,26 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { SwitchPlatformAccessory } from './switchPlatformAccessory'; +import { LightbulbPlatformAccessory } from './lightbulbPlatformAccessory'; +import { BlindPlatformAccessory } from './blindPlatformAccessory'; +import { WindowPlatformAccessory } from './windowPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './garagedoorPlatformAccessory'; +import { ThermostatPlatformAccessory } from './thermostatPlatformAccessory'; +import { FanPlatformAccessory } from './fanPlatformAccessory'; +import { OutletPlatformAccessory } from './outletPlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; export class FilterMaintenancePlatformAccessory implements AccessoryPlugin { @@ -13,6 +33,9 @@ export class FilterMaintenancePlatformAccessory implements AccessoryPlugin { private service: Service; private information: Service; + private subs: any[]; + public services: Service[]; + private platform: any; private device: any; private pushButton: number; @@ -27,8 +50,9 @@ export class FilterMaintenancePlatformAccessory implements AccessoryPlugin { }; name: string; + isParentAccessory: boolean; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -37,10 +61,19 @@ export class FilterMaintenancePlatformAccessory implements AccessoryPlugin { this.pushButton = this.device.pushButton || this.platform.pushButton; this.logging = this.device.logging || 0; + this.subs = []; + this.services = []; + + this.isParentAccessory = false; + this.errorCheck(); this.service = new this.api.hap.Service.FilterMaintenance(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.platform.Characteristic.FilterChangeIndication) .onGet(this.getFilterChangeIndication.bind(this)); @@ -60,6 +93,98 @@ export class FilterMaintenancePlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } + + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateFilterChangeIndicationQueued = false; this.updateFilterLifeLevelQueued = false; @@ -86,7 +211,7 @@ export class FilterMaintenancePlatformAccessory implements AccessoryPlugin { } getServices(): Service[] { - return [ this.information, this.service ]; + return this.services; } async setResetFilterIndication(value: CharacteristicValue) { diff --git a/src/accessories/garagedoorPlatformAccessory.ts b/src/accessories/garagedoorPlatformAccessory.ts index a3e7ec1..38d7f20 100644 --- a/src/accessories/garagedoorPlatformAccessory.ts +++ b/src/accessories/garagedoorPlatformAccessory.ts @@ -4,6 +4,26 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { SwitchPlatformAccessory } from './switchPlatformAccessory'; +import { LightbulbPlatformAccessory } from './lightbulbPlatformAccessory'; +import { BlindPlatformAccessory } from './blindPlatformAccessory'; +import { WindowPlatformAccessory } from './windowPlatformAccessory'; +import { ThermostatPlatformAccessory } from './thermostatPlatformAccessory'; +import { FanPlatformAccessory } from './fanPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './filterMaintenancePlatformAccessory'; +import { OutletPlatformAccessory } from './outletPlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; export class GaragedoorPlatformAccessory implements AccessoryPlugin { @@ -13,6 +33,9 @@ export class GaragedoorPlatformAccessory implements AccessoryPlugin { private service: Service; private information: Service; + private subs: any[]; + public services: Service[]; + private platform: any; private device: any; private pushButton: number; @@ -31,8 +54,9 @@ export class GaragedoorPlatformAccessory implements AccessoryPlugin { }; name: string; + isParentAccessory: boolean; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -41,11 +65,20 @@ export class GaragedoorPlatformAccessory implements AccessoryPlugin { this.pushButton = this.device.pushButton || this.platform.pushButton; this.logging = this.device.logging || 0; + this.subs = []; + this.services = []; + + this.isParentAccessory = false; + this.errorCheck(); this.currentDoorStateIsTargetDoorStateInLogo = this.checkDoorState(); this.service = new this.api.hap.Service.GarageDoorOpener(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.platform.Characteristic.CurrentDoorState) .onGet(this.getCurrentDoorState.bind(this)); @@ -62,6 +95,98 @@ export class GaragedoorPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } + + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateCurrentDoorStateAndTargetDoorStateQueued = false; this.updateCurrentDoorStateQueued = false; this.updateTargetDoorStateQueued = false; @@ -102,7 +227,7 @@ export class GaragedoorPlatformAccessory implements AccessoryPlugin { } getServices(): Service[] { - return [ this.information, this.service ]; + return this.services; } async setTargetDoorState(value: CharacteristicValue) { diff --git a/src/accessories/irrigationSystemPlatformAccessory.ts b/src/accessories/irrigationSystemPlatformAccessory.ts index ee83430..c89389c 100644 --- a/src/accessories/irrigationSystemPlatformAccessory.ts +++ b/src/accessories/irrigationSystemPlatformAccessory.ts @@ -4,6 +4,7 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory } from '../logo'; import { ValvePlatformAccessory } from './valvePlatformAccessory'; @@ -93,7 +94,7 @@ export class IrrigationSystemPlatformAccessory implements AccessoryPlugin { const configDevices = this.platform.config.devices; for (const dev of configDevices) { - if ((dev.type == "valve") && (dev.valveParentIrrigationSystem == this.name)) { + if ((dev.type == Accessory.Valve) && (dev.valveParentIrrigationSystem == this.name)) { if (this.valveZones.includes(dev.valveZone)) { this.platform.log.error('[%s] zone number [%d] already used on [%s] irrigation system!', dev.name, dev.valveZone, this.name); } diff --git a/src/accessories/lightbulbPlatformAccessory.ts b/src/accessories/lightbulbPlatformAccessory.ts index f6bf4d3..74c362d 100644 --- a/src/accessories/lightbulbPlatformAccessory.ts +++ b/src/accessories/lightbulbPlatformAccessory.ts @@ -4,6 +4,26 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { SwitchPlatformAccessory } from './switchPlatformAccessory'; +import { BlindPlatformAccessory } from './blindPlatformAccessory'; +import { WindowPlatformAccessory } from './windowPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './garagedoorPlatformAccessory'; +import { ThermostatPlatformAccessory } from './thermostatPlatformAccessory'; +import { FanPlatformAccessory } from './fanPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './filterMaintenancePlatformAccessory'; +import { OutletPlatformAccessory } from './outletPlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; export class LightbulbPlatformAccessory implements AccessoryPlugin { @@ -14,6 +34,7 @@ export class LightbulbPlatformAccessory implements AccessoryPlugin { private information: Service; private fakegatoService: any; + private subs: any[]; public services: Service[]; private platform: any; @@ -31,8 +52,9 @@ export class LightbulbPlatformAccessory implements AccessoryPlugin { }; name: string; + isParentAccessory: boolean; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -44,12 +66,19 @@ export class LightbulbPlatformAccessory implements AccessoryPlugin { this.withBrightness = false; this.fakegatoService = []; + this.subs = []; this.services = []; + this.isParentAccessory = false; + this.errorCheck(); this.service = new this.api.hap.Service.Lightbulb(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.platform.Characteristic.On) .onSet(this.setOn.bind(this)) .onGet(this.getOn.bind(this)); @@ -66,8 +95,98 @@ export class LightbulbPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } + + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.services.push(this.service, this.information); + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateBrightnessQueued = false; this.updateOnQueued = false; diff --git a/src/accessories/otherPlatformAccessory.ts b/src/accessories/otherPlatformAccessory.ts new file mode 100644 index 0000000..47193dd --- /dev/null +++ b/src/accessories/otherPlatformAccessory.ts @@ -0,0 +1,173 @@ +// each service must implement at-minimum the "required characteristics" for the given service type +// see https://developers.homebridge.io/#/service/Lightbulb + +import { AccessoryPlugin, API, Service, CharacteristicValue } from 'homebridge'; + +import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { SwitchPlatformAccessory } from './switchPlatformAccessory'; +import { LightbulbPlatformAccessory } from './lightbulbPlatformAccessory'; +import { BlindPlatformAccessory } from './blindPlatformAccessory'; +import { WindowPlatformAccessory } from './windowPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './garagedoorPlatformAccessory'; +import { ThermostatPlatformAccessory } from './thermostatPlatformAccessory'; +import { FanPlatformAccessory } from './fanPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './filterMaintenancePlatformAccessory'; +import { OutletPlatformAccessory } from './outletPlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; + +export class OtherPlatformAccessory implements AccessoryPlugin { + + private model: string = "Other"; + + private api: API; + private service: Service; + private information: Service; + + private subs: any[]; + public services: Service[]; + + private platform: any; + private device: any; + + name: string; + isParentAccessory: boolean; + + constructor( api: API, platform: any, device: any ) { + + this.name = device.name; + this.api = api; + this.platform = platform; + this.device = device; + + this.subs = []; + this.services = []; + + this.isParentAccessory = false; + + this.errorCheck(); + + this.service = new this.api.hap.Service.ServiceLabel(this.device.name); + + this.service.getCharacteristic(this.platform.Characteristic.ServiceLabelNamespace) + .onGet(this.getServiceLabelNamespace.bind(this)); + + this.information = new this.api.hap.Service.AccessoryInformation() + .setCharacteristic(this.api.hap.Characteristic.Manufacturer, this.platform.manufacturer) + .setCharacteristic(this.api.hap.Characteristic.Model, this.model + ' @ ' + this.platform.model) + .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) + .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } + + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + + this.services.push(this.service, this.information); + + } + + errorCheck() { + + } + + getServices(): Service[] { + return this.services; + } + + async getServiceLabelNamespace(): Promise { + // validValues: [0, 1], + return 0; + } + +} diff --git a/src/accessories/outletPlatformAccessory.ts b/src/accessories/outletPlatformAccessory.ts index 7b3a422..f685e6f 100644 --- a/src/accessories/outletPlatformAccessory.ts +++ b/src/accessories/outletPlatformAccessory.ts @@ -7,6 +7,26 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { SwitchPlatformAccessory } from './switchPlatformAccessory'; +import { LightbulbPlatformAccessory } from './lightbulbPlatformAccessory'; +import { BlindPlatformAccessory } from './blindPlatformAccessory'; +import { WindowPlatformAccessory } from './windowPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './garagedoorPlatformAccessory'; +import { ThermostatPlatformAccessory } from './thermostatPlatformAccessory'; +import { FanPlatformAccessory } from './fanPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './filterMaintenancePlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; export class OutletPlatformAccessory implements AccessoryPlugin { @@ -17,6 +37,7 @@ export class OutletPlatformAccessory implements AccessoryPlugin { private information: Service; private fakegatoService: any; + private subs: any[]; public services: Service[]; private platform: any; @@ -33,8 +54,9 @@ export class OutletPlatformAccessory implements AccessoryPlugin { }; name: string; + isParentAccessory: boolean; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -45,12 +67,19 @@ export class OutletPlatformAccessory implements AccessoryPlugin { this.inUseIsSet = false; this.fakegatoService = []; + this.subs = []; this.services = []; + this.isParentAccessory = false; + this.errorCheck(); this.service = new this.api.hap.Service.Outlet(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.platform.Characteristic.On) .onSet(this.setOn.bind(this)) .onGet(this.getOn.bind(this)); @@ -64,8 +93,98 @@ export class OutletPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } + + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.services.push(this.service, this.information); + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateOnQueued = false; this.updateInUseQueued = false; diff --git a/src/accessories/switchPlatformAccessory.ts b/src/accessories/switchPlatformAccessory.ts index 9c55ffb..3687361 100644 --- a/src/accessories/switchPlatformAccessory.ts +++ b/src/accessories/switchPlatformAccessory.ts @@ -7,6 +7,26 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { LightbulbPlatformAccessory } from './lightbulbPlatformAccessory'; +import { BlindPlatformAccessory } from './blindPlatformAccessory'; +import { WindowPlatformAccessory } from './windowPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './garagedoorPlatformAccessory'; +import { ThermostatPlatformAccessory } from './thermostatPlatformAccessory'; +import { FanPlatformAccessory } from './fanPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './filterMaintenancePlatformAccessory'; +import { OutletPlatformAccessory } from './outletPlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; export class SwitchPlatformAccessory implements AccessoryPlugin { @@ -17,6 +37,7 @@ export class SwitchPlatformAccessory implements AccessoryPlugin { private information: Service; private fakegatoService: any; + private subs: any[]; public services: Service[]; private platform: any; @@ -30,8 +51,9 @@ export class SwitchPlatformAccessory implements AccessoryPlugin { }; name: string; + isParentAccessory: boolean; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -41,12 +63,19 @@ export class SwitchPlatformAccessory implements AccessoryPlugin { this.logging = this.device.logging || 0; this.fakegatoService = []; + this.subs = []; this.services = []; + this.isParentAccessory = false; + this.errorCheck(); this.service = new this.api.hap.Service.Switch(this.device.name); - + + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.On) .onSet(this.setOn.bind(this)) .onGet(this.getOn.bind(this)); @@ -57,7 +86,100 @@ export class SwitchPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + if (!parent) { + + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } + } + + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } this.updateOnQueued = false; diff --git a/src/accessories/thermostatPlatformAccessory.ts b/src/accessories/thermostatPlatformAccessory.ts index 5eb35af..2c3fa5d 100644 --- a/src/accessories/thermostatPlatformAccessory.ts +++ b/src/accessories/thermostatPlatformAccessory.ts @@ -4,6 +4,26 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { SwitchPlatformAccessory } from './switchPlatformAccessory'; +import { LightbulbPlatformAccessory } from './lightbulbPlatformAccessory'; +import { BlindPlatformAccessory } from './blindPlatformAccessory'; +import { WindowPlatformAccessory } from './windowPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './garagedoorPlatformAccessory'; +import { FanPlatformAccessory } from './fanPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './filterMaintenancePlatformAccessory'; +import { OutletPlatformAccessory } from './outletPlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; export class ThermostatPlatformAccessory implements AccessoryPlugin { @@ -14,6 +34,7 @@ export class ThermostatPlatformAccessory implements AccessoryPlugin { private information: Service; private fakegatoService: any; + private subs: any[]; public services: Service[]; private platform: any; @@ -36,8 +57,9 @@ export class ThermostatPlatformAccessory implements AccessoryPlugin { }; name: string; + isParentAccessory: boolean; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -47,12 +69,19 @@ export class ThermostatPlatformAccessory implements AccessoryPlugin { this.logging = this.device.logging || 0; this.fakegatoService = []; + this.subs = []; this.services = []; + this.isParentAccessory = false; + this.errorCheck(); this.service = new this.api.hap.Service.Thermostat(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState) .onGet(this.getCurrentHeatingCoolingState.bind(this)); @@ -76,12 +105,102 @@ export class ThermostatPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); - this.services.push(this.service, this.information); + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } - this.updateCurrentHeatingCoolingStateQueued = false; - this.updateTargetHeatingCoolingStateQueued = false; - this.updateCurrentTemperatureQueued = false; - this.updateTargetTemperatureQueued = false; + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + + this.updateCurrentHeatingCoolingStateQueued = false; + this.updateTargetHeatingCoolingStateQueued = false; + this.updateCurrentTemperatureQueued = false; + this.updateTargetTemperatureQueued = false; if (this.platform.config.updateInterval) { setInterval(() => { diff --git a/src/accessories/valvePlatformAccessory.ts b/src/accessories/valvePlatformAccessory.ts index e8eaaef..cc25790 100644 --- a/src/accessories/valvePlatformAccessory.ts +++ b/src/accessories/valvePlatformAccessory.ts @@ -13,6 +13,9 @@ export class ValvePlatformAccessory implements AccessoryPlugin { public service: Service; private information: Service; + private subs: any[]; + public services: Service[]; + private platform: any; private device: any; private pushButton: number; @@ -43,6 +46,9 @@ export class ValvePlatformAccessory implements AccessoryPlugin { this.pushButton = this.device.pushButton || this.platform.pushButton; this.logging = this.device.logging || 0; + this.subs = []; + this.services = []; + this.errorCheck(); this.accStates.ValveType = this.device.valveType; @@ -91,6 +97,8 @@ export class ValvePlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + this.services.push(this.service, this.information); + if (parent){ parent.service.addLinkedService(this.service); parent.services.push(this.service); @@ -132,7 +140,7 @@ export class ValvePlatformAccessory implements AccessoryPlugin { } getServices(): Service[] { - return [ this.information, this.service ]; + return this.services; } async setActive(value: CharacteristicValue) { diff --git a/src/accessories/windowPlatformAccessory.ts b/src/accessories/windowPlatformAccessory.ts index 2cdc53d..0efc0d5 100644 --- a/src/accessories/windowPlatformAccessory.ts +++ b/src/accessories/windowPlatformAccessory.ts @@ -4,6 +4,26 @@ import { QueueSendItem, QueueReceiveItem } from "../queue"; import { ErrorNumber } from "../error"; import { LoggerType, InfluxDBLogItem, InfluxDBFild } from "../logger"; import { md5 } from "../md5"; +import { Accessory, SubAccessory } from '../logo'; + +import { SwitchPlatformAccessory } from './switchPlatformAccessory'; +import { LightbulbPlatformAccessory } from './lightbulbPlatformAccessory'; +import { BlindPlatformAccessory } from './blindPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './garagedoorPlatformAccessory'; +import { ThermostatPlatformAccessory } from './thermostatPlatformAccessory'; +import { FanPlatformAccessory } from './fanPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './filterMaintenancePlatformAccessory'; +import { OutletPlatformAccessory } from './outletPlatformAccessory'; + +import { LightSensorPlatformAccessory } from '../sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from '../sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from '../sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from '../sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from '../sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from '../sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from '../sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from '../sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from '../sensors/leakSensorPlatformAccessory'; export class WindowPlatformAccessory implements AccessoryPlugin { @@ -13,6 +33,9 @@ export class WindowPlatformAccessory implements AccessoryPlugin { private service: Service; private information: Service; + private subs: any[]; + public services: Service[]; + private platform: any; private device: any; private pushButton: number; @@ -31,8 +54,9 @@ export class WindowPlatformAccessory implements AccessoryPlugin { }; name: string; + isParentAccessory: boolean; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -41,10 +65,19 @@ export class WindowPlatformAccessory implements AccessoryPlugin { this.pushButton = this.device.pushButton || this.platform.pushButton; this.logging = this.device.logging || 0; + this.subs = []; + this.services = []; + + this.isParentAccessory = false; + this.errorCheck(); this.currentPositionIsTargetPositionInLogo = this.checkPosition(); this.service = new this.api.hap.Service.Window(this.device.name); + + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } this.service.getCharacteristic(this.platform.Characteristic.CurrentPosition) .onGet(this.getCurrentPosition.bind(this)); @@ -62,6 +95,98 @@ export class WindowPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + const configDevices = this.platform.config.devices; + for (const dev of configDevices) { + + if (dev.parentAccessory == this.name) { + this.isParentAccessory = true; + + switch (dev.type) { + case Accessory.Switch: + this.subs.push( new SwitchPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Lightbulb: + this.subs.push( new LightbulbPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Blind: + this.subs.push( new BlindPlatformAccessory(api, platform, dev, this) ); + + case Accessory.Window: + this.subs.push( new WindowPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Garagedoor: + this.subs.push( new GaragedoorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Thermostat: + this.subs.push( new ThermostatPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Fan: + this.subs.push( new FanPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.FilterMaintenance: + this.subs.push( new FilterMaintenancePlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.Outlet: + this.subs.push( new OutletPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LightSensor: + this.subs.push( new LightSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.MotionSensor: + this.subs.push( new MotionSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.ContactSensor: + this.subs.push( new ContactSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.SmokeSensor: + this.subs.push( new SmokeSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.TemperatureSensor: + this.subs.push( new TemperatureSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.HumiditySensor: + this.subs.push( new HumiditySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.CarbonDioxideSensor: + this.subs.push( new CarbonDioxideSensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.AirQualitySensor: + this.subs.push( new AirQualitySensorPlatformAccessory(api, platform, dev, this) ); + break; + + case Accessory.LeakSensor: + this.subs.push( new LeakSensorPlatformAccessory(api, platform, dev, this) ); + break; + } + } + } + + if (this.isParentAccessory == true) { + this.service.subtype = 'main-' + this.model + "-" + this.name.replace(" ", "-"); + } + + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateCurrentPositionAndTargetPositionQueued = false; this.updateCurrentPositionQueued = false; this.updateTargetPositionQueued = false; @@ -102,7 +227,7 @@ export class WindowPlatformAccessory implements AccessoryPlugin { } getServices(): Service[] { - return [ this.information, this.service ]; + return this.services; } async setTargetPosition(value: CharacteristicValue) { diff --git a/src/logo.ts b/src/logo.ts index 1c8a6b2..b9fe2f6 100644 --- a/src/logo.ts +++ b/src/logo.ts @@ -1,3 +1,28 @@ +import { AccessoryPlugin, API, StaticPlatformPlugin } from 'homebridge'; + +import { SwitchPlatformAccessory } from './accessories/switchPlatformAccessory'; +import { LightbulbPlatformAccessory } from './accessories/lightbulbPlatformAccessory'; +import { BlindPlatformAccessory } from './accessories/blindPlatformAccessory'; +import { WindowPlatformAccessory } from './accessories/windowPlatformAccessory'; +import { GaragedoorPlatformAccessory } from './accessories/garagedoorPlatformAccessory'; +import { ThermostatPlatformAccessory } from './accessories/thermostatPlatformAccessory'; +import { IrrigationSystemPlatformAccessory } from './accessories/irrigationSystemPlatformAccessory'; +import { ValvePlatformAccessory } from './accessories/valvePlatformAccessory'; +import { FanPlatformAccessory } from './accessories/fanPlatformAccessory'; +import { FilterMaintenancePlatformAccessory } from './accessories/filterMaintenancePlatformAccessory'; +import { OutletPlatformAccessory } from './accessories/outletPlatformAccessory'; +import { OtherPlatformAccessory } from './accessories/otherPlatformAccessory'; + +import { LightSensorPlatformAccessory } from './sensors/lightSensorPlatformAccessory'; +import { MotionSensorPlatformAccessory } from './sensors/motionSensorPlatformAccessory'; +import { ContactSensorPlatformAccessory } from './sensors/contactSensorPlatformAccessory'; +import { SmokeSensorPlatformAccessory } from './sensors/smokeSensorPlatformAccessory'; +import { TemperatureSensorPlatformAccessory } from './sensors/temperatureSensorPlatformAccessory'; +import { HumiditySensorPlatformAccessory } from './sensors/humiditySensorPlatformAccessory'; +import { CarbonDioxideSensorPlatformAccessory } from './sensors/carbonDioxideSensorPlatformAccessory'; +import { AirQualitySensorPlatformAccessory } from './sensors/airQualitySensorPlatformAccessory'; +import { LeakSensorPlatformAccessory } from './sensors/leakSensorPlatformAccessory'; + export class LogoType { static T_0BA7: string = "0BA7"; static T_0BA8: string = "0BA8"; @@ -18,4 +43,142 @@ export class LogoDefault { static QueueInterval: number = 100; static QueueSize: number = 100; static QueueMinSize: number = 0; +} + +export class Accessory { + static Switch: string = "switch"; + static Lightbulb: string = "lightbulb"; + static Blind: string = "blind"; + static Window: string = "window"; + static Garagedoor: string = "garagedoor"; + static Thermostat: string = "thermostat"; + static IrrigationSystem: string = "irrigationSystem"; + static Valve: string = "valve"; + static Fan: string = "fan"; + static FilterMaintenance: string = "filterMaintenance"; + static Outlet: string = "outlet"; + static Other: string = "other"; + static LightSensor: string = "lightSensor"; + static MotionSensor: string = "motionSensor"; + static ContactSensor: string = "contactSensor"; + static SmokeSensor: string = "smokeSensor"; + static TemperatureSensor: string = "temperatureSensor"; + static HumiditySensor: string = "humiditySensor"; + static CarbonDioxideSensor: string = "carbonDioxideSensor"; + static AirQualitySensor: string = "airQualitySensor"; + static LeakSensor: string = "leakSensor"; +} + +export class SubAccessory { + + api: API; + platform: StaticPlatformPlugin; + + constructor (api: API, platform: StaticPlatformPlugin) { + + this.api = api; + this.platform = platform; + + } + + getNewAccessory(device:any, parent: any): SwitchPlatformAccessory | LightbulbPlatformAccessory | BlindPlatformAccessory | + WindowPlatformAccessory | GaragedoorPlatformAccessory | ThermostatPlatformAccessory | + IrrigationSystemPlatformAccessory | ValvePlatformAccessory | FanPlatformAccessory | + FilterMaintenancePlatformAccessory | OutletPlatformAccessory | OtherPlatformAccessory | + LightSensorPlatformAccessory | MotionSensorPlatformAccessory | ContactSensorPlatformAccessory | + SmokeSensorPlatformAccessory | TemperatureSensorPlatformAccessory | HumiditySensorPlatformAccessory | + CarbonDioxideSensorPlatformAccessory | AirQualitySensorPlatformAccessory | LeakSensorPlatformAccessory | + AccessoryPlugin | undefined { + + switch (device.type) { + case Accessory.Switch: + return new SwitchPlatformAccessory(this.api, this.platform, device, parent); + break; + + case Accessory.Lightbulb: + return new LightbulbPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.Blind: + return new BlindPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.Window: + return new WindowPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.Garagedoor: + return new GaragedoorPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.Thermostat: + return new ThermostatPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.IrrigationSystem: + return new IrrigationSystemPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.Valve: + if (!(device.valveParentIrrigationSystem)){ + return new ValvePlatformAccessory(this.api, this.platform, device, parent); + } + break; + + case Accessory.Fan: + return new FanPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.FilterMaintenance: + return new FilterMaintenancePlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.Outlet: + return new OutletPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.Other: + return new OtherPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.LightSensor: + return new LightSensorPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.MotionSensor: + return new MotionSensorPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.ContactSensor: + return new ContactSensorPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.SmokeSensor: + return new SmokeSensorPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.TemperatureSensor: + return new TemperatureSensorPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.HumiditySensor: + return new HumiditySensorPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.CarbonDioxideSensor: + return new CarbonDioxideSensorPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.AirQualitySensor: + return new AirQualitySensorPlatformAccessory(this.api, this.platform, device); + break; + + case Accessory.LeakSensor: + return new LeakSensorPlatformAccessory(this.api, this.platform, device); + break; + + } + + } + } \ No newline at end of file diff --git a/src/platform.ts b/src/platform.ts index 661a6bf..5e52c8c 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -8,7 +8,8 @@ HDMI Pi: Homebridge v1.7.0 (HAP v0.11.1) NPM v10.2.3 NODE v20.5.1 -> Homebridge requires Node.js version of ^18.15.0 || ^20.7.0 which does not satisfy the current Node.js version of v20.5.1. You may need to upgrade your installation of Node.js - see https://homebridge.io/w/JTKEF -*/ + + */ import { API, AccessoryPlugin, Service, Characteristic, StaticPlatformPlugin, Logging, PlatformConfig } from "homebridge"; @@ -19,7 +20,7 @@ import { Queue, QueueSendItem, QueueReceiveItem } from "./queue"; import { ErrorNumber } from "./error"; import { LoggerType, LoggerInterval } from "./logger"; -import { LogoType, LogoInterface, LogoDefault } from "./logo"; +import { LogoType, LogoInterface, LogoDefault, Accessory } from "./logo"; import { SwitchPlatformAccessory } from './accessories/switchPlatformAccessory'; import { LightbulbPlatformAccessory } from './accessories/lightbulbPlatformAccessory'; @@ -32,6 +33,7 @@ import { ValvePlatformAccessory } from './accessories/valvePlatformA import { FanPlatformAccessory } from './accessories/fanPlatformAccessory'; import { FilterMaintenancePlatformAccessory } from './accessories/filterMaintenancePlatformAccessory'; import { OutletPlatformAccessory } from './accessories/outletPlatformAccessory'; +import { OtherPlatformAccessory } from './accessories/otherPlatformAccessory'; import { LightSensorPlatformAccessory } from './sensors/lightSensorPlatformAccessory'; import { MotionSensorPlatformAccessory } from './sensors/motionSensorPlatformAccessory'; @@ -114,7 +116,6 @@ export class LogoHomebridgePlatform implements StaticPlatformPlugin { this.model = pjson.model; this.firmwareRevision = pjson.version; this.pushButton = (this.config.pushButton ? 1 : 0); - if (Array.isArray(this.config.devices)) { @@ -123,114 +124,157 @@ export class LogoHomebridgePlatform implements StaticPlatformPlugin { for (const device of configDevices) { if (this.config.debugMsgLog == true) { - this.log.info('Adding new accessory:', device.name); + this.log.info('Adding new accessory: ', device.name); } switch (device.type) { - case "switch": - this.accessoriesArray.push( new SwitchPlatformAccessory(this.api, this, device) ); + case Accessory.Switch: + if (!(device.parentAccessory)){ + this.accessoriesArray.push( new SwitchPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 1; break; - case "lightbulb": - this.accessoriesArray.push( new LightbulbPlatformAccessory(this.api, this, device) ); + case Accessory.Lightbulb: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new LightbulbPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 2; break; - case "blind": - this.accessoriesArray.push( new BlindPlatformAccessory(this.api, this, device) ); + case Accessory.Blind: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new BlindPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 3; break; - case "window": - this.accessoriesArray.push( new WindowPlatformAccessory(this.api, this, device) ); + case Accessory.Window: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new WindowPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 3; break; - case "garagedoor": - this.accessoriesArray.push( new GaragedoorPlatformAccessory(this.api, this, device) ); + case Accessory.Garagedoor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new GaragedoorPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 3; break; - case "thermostat": - this.accessoriesArray.push( new ThermostatPlatformAccessory(this.api, this, device) ); + case Accessory.Thermostat: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new ThermostatPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 4; break; - case "irrigationSystem": + case Accessory.IrrigationSystem: this.accessoriesArray.push( new IrrigationSystemPlatformAccessory(this.api, this, device) ); this.queueMinSize += 5; break; - case "valve": + case Accessory.Valve: if (!(device.valveParentIrrigationSystem)){ this.accessoriesArray.push( new ValvePlatformAccessory(this.api, this, device) ); } this.queueMinSize += 5; break; - case "fan": - this.accessoriesArray.push( new FanPlatformAccessory(this.api, this, device) ); + case Accessory.Fan: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new FanPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 3; break; - case "filterMaintenance": - this.accessoriesArray.push( new FilterMaintenancePlatformAccessory(this.api, this, device) ); + case Accessory.FilterMaintenance: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new FilterMaintenancePlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 2; break; - case "lightSensor": - this.accessoriesArray.push( new LightSensorPlatformAccessory(this.api, this, device) ); + case Accessory.Outlet: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new OutletPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 1; break; - case "motionSensor": - this.accessoriesArray.push( new MotionSensorPlatformAccessory(this.api, this, device) ); + case Accessory.Other: + this.accessoriesArray.push( new OtherPlatformAccessory(this.api, this, device) ); this.queueMinSize += 1; break; - case "contactSensor": - this.accessoriesArray.push( new ContactSensorPlatformAccessory(this.api, this, device) ); + case Accessory.LightSensor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new LightSensorPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 1; break; - case "smokeSensor": - this.accessoriesArray.push( new SmokeSensorPlatformAccessory(this.api, this, device) ); + case Accessory.MotionSensor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new MotionSensorPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 1; break; - case "temperatureSensor": - this.accessoriesArray.push( new TemperatureSensorPlatformAccessory(this.api, this, device) ); + case Accessory.ContactSensor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new ContactSensorPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 1; break; - case "humiditySensor": - this.accessoriesArray.push( new HumiditySensorPlatformAccessory(this.api, this, device) ); + case Accessory.SmokeSensor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new SmokeSensorPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 1; break; - case "carbonDioxideSensor": - this.accessoriesArray.push( new CarbonDioxideSensorPlatformAccessory(this.api, this, device) ); - this.queueMinSize += 3; + case Accessory.TemperatureSensor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new TemperatureSensorPlatformAccessory(this.api, this, device) ); + } + this.queueMinSize += 1; break; - case "airQualitySensor": - this.accessoriesArray.push( new AirQualitySensorPlatformAccessory(this.api, this, device) ); + case Accessory.HumiditySensor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new HumiditySensorPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 1; break; - case "leakSensor": - this.accessoriesArray.push( new LeakSensorPlatformAccessory(this.api, this, device) ); - this.queueMinSize += 2; + case Accessory.CarbonDioxideSensor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new CarbonDioxideSensorPlatformAccessory(this.api, this, device) ); + } + this.queueMinSize += 3; break; - case "outlet": - this.accessoriesArray.push( new OutletPlatformAccessory(this.api, this, device) ); + case Accessory.AirQualitySensor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new AirQualitySensorPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 1; break; + + case Accessory.LeakSensor: + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new LeakSensorPlatformAccessory(this.api, this, device) ); + } + this.queueMinSize += 2; + break; default: - this.accessoriesArray.push( new SwitchPlatformAccessory(this.api, this, device) ); + if (!(device.parentAccessory)) { + this.accessoriesArray.push( new SwitchPlatformAccessory(this.api, this, device) ); + } this.queueMinSize += 1; break; } diff --git a/src/sensors/airQualitySensorPlatformAccessory.ts b/src/sensors/airQualitySensorPlatformAccessory.ts index b133d0b..018a9fe 100644 --- a/src/sensors/airQualitySensorPlatformAccessory.ts +++ b/src/sensors/airQualitySensorPlatformAccessory.ts @@ -13,6 +13,8 @@ export class AirQualitySensorPlatformAccessory implements AccessoryPlugin { private service: Service; private information: Service; + public services: Service[]; + private platform: any; private device: any; private logging: number; @@ -24,7 +26,7 @@ export class AirQualitySensorPlatformAccessory implements AccessoryPlugin { name: string; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -32,10 +34,16 @@ export class AirQualitySensorPlatformAccessory implements AccessoryPlugin { this.device = device; this.logging = this.device.logging || 0; + this.services = []; + this.errorCheck(); this.service = new this.api.hap.Service.AirQualitySensor(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.AirQuality) .onGet(this.getAirQuality.bind(this)); @@ -45,6 +53,13 @@ export class AirQualitySensorPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateAirQualityQueued = false; if (this.platform.config.updateInterval) { @@ -69,7 +84,7 @@ export class AirQualitySensorPlatformAccessory implements AccessoryPlugin { } getServices(): Service[] { - return [ this.information, this.service ]; + return this.services; } async getAirQuality(): Promise { diff --git a/src/sensors/carbonDioxideSensorPlatformAccessory.ts b/src/sensors/carbonDioxideSensorPlatformAccessory.ts index 243210d..e5ae5ab 100644 --- a/src/sensors/carbonDioxideSensorPlatformAccessory.ts +++ b/src/sensors/carbonDioxideSensorPlatformAccessory.ts @@ -31,7 +31,7 @@ export class CarbonDioxideSensorPlatformAccessory implements AccessoryPlugin { name: string; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -46,6 +46,10 @@ export class CarbonDioxideSensorPlatformAccessory implements AccessoryPlugin { this.service = new this.api.hap.Service.CarbonDioxideSensor(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.CarbonDioxideDetected) .onGet(this.getCarbonDioxideDetected.bind(this)); @@ -66,6 +70,11 @@ export class CarbonDioxideSensorPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } this.updateCarbonDioxideDetectedQueued = false; this.updateCarbonDioxideLevelQueued = false; diff --git a/src/sensors/contactSensorPlatformAccessory.ts b/src/sensors/contactSensorPlatformAccessory.ts index 05cdf51..e838c06 100644 --- a/src/sensors/contactSensorPlatformAccessory.ts +++ b/src/sensors/contactSensorPlatformAccessory.ts @@ -27,7 +27,7 @@ export class ContactSensorPlatformAccessory implements AccessoryPlugin { name: string; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -42,6 +42,10 @@ export class ContactSensorPlatformAccessory implements AccessoryPlugin { this.service = new this.api.hap.Service.ContactSensor(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.ContactSensorState) .onGet(this.getContactSensorState.bind(this)); @@ -53,6 +57,11 @@ export class ContactSensorPlatformAccessory implements AccessoryPlugin { this.services.push(this.service, this.information); + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateContactSensorStateQueued = false; if (this.platform.config.updateInterval) { diff --git a/src/sensors/humiditySensorPlatformAccessory.ts b/src/sensors/humiditySensorPlatformAccessory.ts index 73ac84c..7dc8fdf 100644 --- a/src/sensors/humiditySensorPlatformAccessory.ts +++ b/src/sensors/humiditySensorPlatformAccessory.ts @@ -29,7 +29,7 @@ export class HumiditySensorPlatformAccessory implements AccessoryPlugin { name: string; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -44,10 +44,13 @@ export class HumiditySensorPlatformAccessory implements AccessoryPlugin { this.service = new this.api.hap.Service.HumiditySensor(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.CurrentRelativeHumidity) .onGet(this.getCurrentRelativeHumidity.bind(this)); - this.information = new this.api.hap.Service.AccessoryInformation() .setCharacteristic(this.api.hap.Characteristic.Manufacturer, this.platform.manufacturer) .setCharacteristic(this.api.hap.Characteristic.Model, this.model + ' @ ' + this.platform.model) @@ -55,6 +58,11 @@ export class HumiditySensorPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } this.updateCurrentRelativeHumidityQueued = false; diff --git a/src/sensors/leakSensorPlatformAccessory.ts b/src/sensors/leakSensorPlatformAccessory.ts index 0380598..be6b4ad 100644 --- a/src/sensors/leakSensorPlatformAccessory.ts +++ b/src/sensors/leakSensorPlatformAccessory.ts @@ -13,6 +13,8 @@ export class LeakSensorPlatformAccessory implements AccessoryPlugin { private service: Service; private information: Service; + public services: Service[]; + private platform: any; private device: any; private logging: number; @@ -26,7 +28,7 @@ export class LeakSensorPlatformAccessory implements AccessoryPlugin { name: string; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -34,10 +36,16 @@ export class LeakSensorPlatformAccessory implements AccessoryPlugin { this.device = device; this.logging = this.device.logging || 0; + this.services = []; + this.errorCheck(); this.service = new this.api.hap.Service.LeakSensor(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.LeakDetected) .onGet(this.getLeakDetected.bind(this)); @@ -52,6 +60,13 @@ export class LeakSensorPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateLeakDetectedQueued = false; this.updateWaterLevelQueued = false; @@ -78,7 +93,7 @@ export class LeakSensorPlatformAccessory implements AccessoryPlugin { } getServices(): Service[] { - return [ this.information, this.service ]; + return this.services; } async getLeakDetected(): Promise { diff --git a/src/sensors/lightSensorPlatformAccessory.ts b/src/sensors/lightSensorPlatformAccessory.ts index e389a6d..70aac97 100644 --- a/src/sensors/lightSensorPlatformAccessory.ts +++ b/src/sensors/lightSensorPlatformAccessory.ts @@ -29,7 +29,7 @@ export class LightSensorPlatformAccessory implements AccessoryPlugin { name: string; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -44,6 +44,10 @@ export class LightSensorPlatformAccessory implements AccessoryPlugin { this.service = new this.api.hap.Service.LightSensor(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.CurrentAmbientLightLevel) .onGet(this.getCurrentAmbientLightLevel.bind(this)); @@ -55,6 +59,11 @@ export class LightSensorPlatformAccessory implements AccessoryPlugin { this.services.push(this.service, this.information); + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateCurrentAmbientLightLevelQueued = false; if (this.platform.config.updateInterval) { diff --git a/src/sensors/motionSensorPlatformAccessory.ts b/src/sensors/motionSensorPlatformAccessory.ts index 31b87dd..af9b9a6 100644 --- a/src/sensors/motionSensorPlatformAccessory.ts +++ b/src/sensors/motionSensorPlatformAccessory.ts @@ -27,7 +27,7 @@ export class MotionSensorPlatformAccessory implements AccessoryPlugin { name: string; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -42,6 +42,10 @@ export class MotionSensorPlatformAccessory implements AccessoryPlugin { this.service = new this.api.hap.Service.MotionSensor(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.MotionDetected) .onGet(this.getMotionDetected.bind(this)); @@ -53,6 +57,11 @@ export class MotionSensorPlatformAccessory implements AccessoryPlugin { this.services.push(this.service, this.information); + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateMotionDetectedQueued = false; if (this.platform.config.updateInterval) { diff --git a/src/sensors/smokeSensorPlatformAccessory.ts b/src/sensors/smokeSensorPlatformAccessory.ts index f8a7b9c..8ab7bbc 100644 --- a/src/sensors/smokeSensorPlatformAccessory.ts +++ b/src/sensors/smokeSensorPlatformAccessory.ts @@ -13,6 +13,8 @@ export class SmokeSensorPlatformAccessory implements AccessoryPlugin { private service: Service; private information: Service; + public services: Service[]; + private platform: any; private device: any; private logging: number; @@ -24,7 +26,7 @@ export class SmokeSensorPlatformAccessory implements AccessoryPlugin { name: string; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -32,10 +34,16 @@ export class SmokeSensorPlatformAccessory implements AccessoryPlugin { this.device = device; this.logging = this.device.logging || 0; + this.services = []; + this.errorCheck(); this.service = new this.api.hap.Service.SmokeSensor(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.SmokeDetected) .onGet(this.getSmokeDetected.bind(this)); @@ -45,6 +53,13 @@ export class SmokeSensorPlatformAccessory implements AccessoryPlugin { .setCharacteristic(this.api.hap.Characteristic.SerialNumber, md5(this.device.name + this.model)) .setCharacteristic(this.api.hap.Characteristic.FirmwareRevision, this.platform.firmwareRevision); + this.services.push(this.service, this.information); + + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateSmokeDetectedQueued = false; if (this.platform.config.updateInterval) { @@ -69,7 +84,7 @@ export class SmokeSensorPlatformAccessory implements AccessoryPlugin { } getServices(): Service[] { - return [ this.information, this.service ]; + return this.services; } async getSmokeDetected(): Promise { diff --git a/src/sensors/temperatureSensorPlatformAccessory.ts b/src/sensors/temperatureSensorPlatformAccessory.ts index 60373b5..4018247 100644 --- a/src/sensors/temperatureSensorPlatformAccessory.ts +++ b/src/sensors/temperatureSensorPlatformAccessory.ts @@ -29,7 +29,7 @@ export class TemperatureSensorPlatformAccessory implements AccessoryPlugin { name: string; - constructor( api: API, platform: any, device: any ) { + constructor( api: API, platform: any, device: any, parent?: any ) { this.name = device.name; this.api = api; @@ -44,6 +44,10 @@ export class TemperatureSensorPlatformAccessory implements AccessoryPlugin { this.service = new this.api.hap.Service.TemperatureSensor(this.device.name); + if (parent) { + this.service.subtype = 'sub-' + this.model + "-" + this.name.replace(" ", "-"); + } + this.service.getCharacteristic(this.api.hap.Characteristic.CurrentTemperature) .setProps({minValue: -100}) .onGet(this.getCurrentTemperature.bind(this)); @@ -56,6 +60,11 @@ export class TemperatureSensorPlatformAccessory implements AccessoryPlugin { this.services.push(this.service, this.information); + if (parent) { + parent.service.addLinkedService(this.service); + parent.services.push(this.service); + } + this.updateCurrentTemperatureQueued = false; if (this.platform.config.updateInterval) {