diff --git a/CHANGELOG.md b/CHANGELOG.md index a377f15..fa60186 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +## 0.2.3 (2021-02-12) + +### New devices + +- **HmIP-eTRV-C**: Heating-thermostat compact without display + +### Improvements + +- **HmIP-eTRV**: Fixed update of valve position. Show valve position changes in logs. +- **HmIP-eTRV**: Valve position > 0 indicates current cooling/heating state: HEAT. Valve position = 0 indicates current + heating cooling/heating state: OFF. +- **HmIP-eTRV**: Added logs for setting ignored values (target cooling/heating mode, display units). +- **HmIP-eTRV**: Target cooling/heating mode is now ignored. Will be used for future mapping of custom states. +- **HmIP-eTRV**: Show changes of valve state in logs. + +### Bugfix + +- **Shutter/Blind**: Fixed spinning progress indicator in Home app. +- **HmIP-eTRV-C**: HmIP-eTRV-C was listed but not actually supported. + ## 0.2.2 (2021-02-11) ### New devices diff --git a/README.md b/README.md index 2d4d64e..a658b0b 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,9 @@ button and note the "auth_token" that is being generated, add it to your config. - HmIP-HAP (Access Point) - HmIP-eTRV (Radiator Thermostat) -- HmIP-eTRV-C (Heating-thermostat compact without display) +- HmIP-eTRV-2 (Radiator Thermostat) +- HmIP-eTRV-B (Radiator Thermostat - basic) +- HmIP-eTRV-C (Heating-thermostat - compact without display) - HmIP-FROLL (Shutter Actuator - flush-mount) - HmIP-BROLL (Shutter Actuator - brand-mount) - HmIP-FBL (Blind Actuator - flush-mount) diff --git a/package-lock.json b/package-lock.json index 1ef4131..8f52984 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "homebridge-homematicip", - "version": "0.2.2", + "version": "0.2.3", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.2.2", + "version": "0.2.3", "license": "Apache-2.0", "dependencies": { "bottleneck": "^2.19.5", diff --git a/package.json b/package.json index 886b72e..349b459 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homebridge-homematicip", - "version": "0.2.2", + "version": "0.2.3", "description": "Homematic IP plugin for homebridge", "license": "Apache-2.0", "author": "Marc Sowen ", diff --git a/src/HmIPPlatform.ts b/src/HmIPPlatform.ts index 0a9af44..aaad030 100644 --- a/src/HmIPPlatform.ts +++ b/src/HmIPPlatform.ts @@ -242,7 +242,8 @@ export class HmIPPlatform implements DynamicPlatformPlugin { || device.type === 'TEMPERATURE_HUMIDITY_SENSOR_OUTDOOR' || device.type === 'TEMPERATURE_HUMIDITY_SENSOR_DISPLAY') { homebridgeDevice = new HmIPClimateSensor(this, hmIPAccessory.accessory); - } else if (device.type === 'HEATING_THERMOSTAT') { + } else if (device.type === 'HEATING_THERMOSTAT' + || device.type === 'HEATING_THERMOSTAT_COMPACT') { homebridgeDevice = new HmIPHeatingThermostat(this, hmIPAccessory.accessory); } else if (device.type === 'FULL_FLUSH_SHUTTER' || device.type === 'BRAND_SHUTTER') { diff --git a/src/devices/HmIPBlind.ts b/src/devices/HmIPBlind.ts index 1db8548..dab92b0 100644 --- a/src/devices/HmIPBlind.ts +++ b/src/devices/HmIPBlind.ts @@ -64,13 +64,19 @@ export class HmIPBlind extends HmIPShutter implements Updateable { if (slatsLevelHomeKit != this.slatsLevel) { this.slatsLevel = slatsLevelHomeKit; this.platform.log.info('Current blind slats level of %s changed to %s', this.accessory.displayName, this.slatsLevel.toFixed(0)); - this.service.updateCharacteristic(this.platform.Characteristic.CurrentHorizontalTiltAngle, slatsLevelHomeKit); + this.service.updateCharacteristic(this.platform.Characteristic.CurrentHorizontalTiltAngle, this.slatsLevel); } - } } } + protected updateProcessingState() { + super.updateProcessingState(); + if (!this.processing) { + this.service.updateCharacteristic(this.platform.Characteristic.TargetHorizontalTiltAngle, this.slatsLevel); + } + } + private static slatsHmIPToHomeKit(hmIPValue: number): number { return -90 + (hmIPValue * 180.0); } diff --git a/src/devices/HmIPHeatingThermostat.ts b/src/devices/HmIPHeatingThermostat.ts index 209b809..15a3872 100644 --- a/src/devices/HmIPHeatingThermostat.ts +++ b/src/devices/HmIPHeatingThermostat.ts @@ -10,13 +10,25 @@ import {HmIPPlatform} from '../HmIPPlatform'; import {HmIPDevice, HmIPGroup, Updateable} from '../HmIPState'; import {HmIPGenericDevice} from './HmIPGenericDevice'; +enum ValveState { + STATE_NOT_AVAILABLE = "STATE_NOT_AVAILABLE", + RUN_TO_START = "RUN_TO_START", + WAIT_FOR_ADAPTION = "WAIT_FOR_ADAPTION", + ADAPTION_IN_PROGRESS = "ADAPTION_IN_PROGRESS", + ADAPTION_DONE = "ADAPTION_DONE", + TOO_TIGHT = "TOO_TIGHT", + ADJUSTMENT_TOO_BIG = "ADJUSTMENT_TOO_BIG", + ADJUSTMENT_TOO_SMALL = "ADJUSTMENT_TOO_SMALL", + ERROR_POSITION = "ERROR_POSITION", +} + interface HeatingThermostatChannel { functionalChannelType: string; valveActualTemperature: number; setPointTemperature: number; valvePosition: number; temperatureOffset: number; - valveState: string; + valveState: ValveState; groups: string[]; } @@ -29,6 +41,7 @@ export class HmIPHeatingThermostat extends HmIPGenericDevice implements Updateab private valveActualTemperature = 0; private setPointTemperature = 0; private valvePosition = 0; + private valveState: ValveState = ValveState.ERROR_POSITION; private heatingGroupId = ''; constructor( @@ -59,20 +72,20 @@ export class HmIPHeatingThermostat extends HmIPGenericDevice implements Updateab this.service.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits) .on('get', this.handleTemperatureDisplayUnitsGet.bind(this)) .on('set', this.handleTemperatureDisplayUnitsSet.bind(this)); - } handleCurrentHeatingCoolingStateGet(callback: CharacteristicGetCallback) { - callback(null, this.valveActualTemperature <= (this.setPointTemperature + 0.1) && this.valvePosition > 0 ? - this.platform.Characteristic.CurrentHeatingCoolingState.HEAT : this.platform.Characteristic.CurrentHeatingCoolingState.COOL); + callback(null, this.valvePosition > 0 ? + this.platform.Characteristic.CurrentHeatingCoolingState.HEAT : this.platform.Characteristic.CurrentHeatingCoolingState.OFF); } handleTargetHeatingCoolingStateGet(callback: CharacteristicGetCallback) { - callback(null, this.valveActualTemperature <= (this.setPointTemperature + 0.1) && this.valvePosition > 0 ? - this.platform.Characteristic.CurrentHeatingCoolingState.HEAT : this.platform.Characteristic.CurrentHeatingCoolingState.COOL); + callback(null, this.platform.Characteristic.TargetHeatingCoolingState.AUTO); } handleTargetHeatingCoolingStateSet(value: CharacteristicValue, callback: CharacteristicSetCallback) { + this.platform.log.info('Ignoring setting heating/cooling state for %s to %s', this.accessory.displayName, + this.getTargetHeatingCoolingStateName(value)); callback(null); } @@ -99,33 +112,41 @@ export class HmIPHeatingThermostat extends HmIPGenericDevice implements Updateab } handleTemperatureDisplayUnitsSet(value: CharacteristicValue, callback: CharacteristicSetCallback) { + this.platform.log.info('Ignoring setting display units for %s to %s', this.accessory.displayName, + value == 0 ? "CELSIUS" : "FAHRENHEIT"); callback(null); } - handleCurrentActuationGet(callback: CharacteristicGetCallback) { - callback(null, this.valvePosition); - } - public updateDevice(hmIPDevice: HmIPDevice, groups: { [key: string]: HmIPGroup }) { super.updateDevice(hmIPDevice, groups); for (const id in hmIPDevice.functionalChannels) { const channel = hmIPDevice.functionalChannels[id]; if (channel.functionalChannelType === 'HEATING_THERMOSTAT_CHANNEL') { - const wthChannel = channel; + const heatingThermostatChannel = channel; - if (wthChannel.setPointTemperature !== this.setPointTemperature) { - this.platform.log.info(`Target temperature of ${this.accessory.displayName} changed to ${wthChannel.setPointTemperature}`); - this.setPointTemperature = wthChannel.setPointTemperature; + if (heatingThermostatChannel.setPointTemperature !== this.setPointTemperature) { + this.setPointTemperature = heatingThermostatChannel.setPointTemperature; + this.platform.log.info('Target temperature of %s changed to %s', this.accessory.displayName, this.setPointTemperature); this.service.updateCharacteristic(this.platform.Characteristic.TargetTemperature, this.setPointTemperature); } - if (wthChannel.valveActualTemperature !== this.valveActualTemperature) { - this.platform.log.info(`Current temperature of ${this.accessory.displayName} changed to ${wthChannel.valveActualTemperature}`); - this.valveActualTemperature = wthChannel.valveActualTemperature; + if (heatingThermostatChannel.valveActualTemperature !== this.valveActualTemperature) { + this.valveActualTemperature = heatingThermostatChannel.valveActualTemperature; + this.platform.log.info('Current temperature of %s changed to %s', this.accessory.displayName, this.valveActualTemperature); this.service.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.valveActualTemperature); } - for (const groupId of wthChannel.groups) { + if (heatingThermostatChannel.valvePosition !== this.valvePosition) { + this.valvePosition = heatingThermostatChannel.valvePosition; + this.platform.log.info('Current valve position of %s changed to %s', this.accessory.displayName, this.valvePosition); + } + + if (heatingThermostatChannel.valveState !== this.valveState) { + this.valveState = heatingThermostatChannel.valveState; + this.platform.log.info('Current valve state of %s changed to %s', this.accessory.displayName, this.valveState); + } + + for (const groupId of heatingThermostatChannel.groups) { if (groups[groupId].type === 'HEATING') { this.heatingGroupId = groupId; } @@ -133,4 +154,20 @@ export class HmIPHeatingThermostat extends HmIPGenericDevice implements Updateab } } } + + private getTargetHeatingCoolingStateName(heatingCoolingState: number): string { + switch (heatingCoolingState) { + case this.platform.Characteristic.TargetHeatingCoolingState.OFF: + return "OFF"; + case this.platform.Characteristic.TargetHeatingCoolingState.HEAT: + return "HEAT"; + case this.platform.Characteristic.TargetHeatingCoolingState.COOL: + return "COOL"; + case this.platform.Characteristic.TargetHeatingCoolingState.AUTO: + return "AUTO"; + default: + return "UNKNOWN"; + } + } + } diff --git a/src/devices/HmIPShutter.ts b/src/devices/HmIPShutter.ts index e8dae8c..e6d1d65 100644 --- a/src/devices/HmIPShutter.ts +++ b/src/devices/HmIPShutter.ts @@ -9,6 +9,7 @@ import { import {HmIPPlatform} from '../HmIPPlatform'; import {HmIPDevice, HmIPGroup, Updateable} from '../HmIPState'; import {HmIPGenericDevice} from './HmIPGenericDevice'; +import {HmIPBlind} from './HmIPBlind'; interface ShutterChannel { functionalChannelType: string; @@ -28,7 +29,7 @@ export class HmIPShutter extends HmIPGenericDevice implements Updateable { // Values are HomeKit style (100..0) protected shutterLevel = 0; - private processing = false; + protected processing = false; constructor( platform: HmIPPlatform, @@ -106,13 +107,22 @@ export class HmIPShutter extends HmIPGenericDevice implements Updateable { if (shutterChannel.processing != this.processing) { this.processing = shutterChannel.processing; this.platform.log.info('Processing state of shutter/blind %s changed to %s', this.accessory.displayName, this.processing); - this.service.updateCharacteristic(this.platform.Characteristic.PositionState, - shutterChannel.processing ? this.platform.Characteristic.PositionState.DECREASING : this.platform.Characteristic.PositionState.STOPPED); + this.updateProcessingState(); } + } } } + protected updateProcessingState() { + if (this.processing) { + this.service.updateCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.DECREASING); + } else { + this.service.updateCharacteristic(this.platform.Characteristic.PositionState, this.platform.Characteristic.PositionState.STOPPED); + this.service.updateCharacteristic(this.platform.Characteristic.TargetPosition, this.shutterLevel); + } + } + protected static shutterHmIPToHomeKit(hmIPValue: number): number { return (1 - hmIPValue) * 100.0; } diff --git a/src/settings.ts b/src/settings.ts index 2cae4e6..ea51f88 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -11,4 +11,4 @@ export const PLUGIN_NAME = 'homebridge-homematicip'; /** * Version to be used in protocol communication */ -export const PLUGIN_VERSION = '0.2.2'; +export const PLUGIN_VERSION = '0.2.3';