Skip to content

Commit

Permalink
feat(heat pump): add ventilation support (#473)
Browse files Browse the repository at this point in the history
* add test cases

* extract quickmodes feature

* add test case

* add test cases

* add ventilation state feature

* add test cases

* add features

* use features

* fix test cases

* consolidate

* reuse ventilation class

* remove feature class

* add ventilation methods

* change order

* adjust test case

* deprecate ventilation functions

* fix type

* add types-deprecated

* add version to deprecated annotation
  • Loading branch information
CFenner authored Dec 30, 2024
1 parent 0aec87c commit 356605a
Show file tree
Hide file tree
Showing 11 changed files with 597 additions and 276 deletions.
47 changes: 11 additions & 36 deletions PyViCare/PyViCareHeatPump.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from contextlib import suppress
from typing import Any, List
from deprecated import deprecated

from PyViCare.PyViCareHeatingDevice import (HeatingDevice,
HeatingDeviceWithComponent)
from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError, handleAPICommandErrors, handleNotSupported
from PyViCare.PyViCareHeatingDevice import HeatingDevice, HeatingDeviceWithComponent
from PyViCare.PyViCareUtils import handleAPICommandErrors, handleNotSupported
from PyViCare.PyViCareVentilationDevice import VentilationDevice


class HeatPump(HeatingDevice):
class HeatPump(HeatingDevice, VentilationDevice):

@property
def compressors(self) -> List[Any]:
Expand Down Expand Up @@ -119,13 +119,11 @@ def getVolumetricFlowReturn(self):
return self.service.getProperty("heating.sensors.volumetricFlow.allengra")["properties"]['value']['value']

@handleNotSupported
@deprecated(reason="renamed, use getVentilationModes", version="2.40.0")
def getAvailableVentilationModes(self):
return self.service.getProperty("ventilation.operating.modes.active")["commands"]["setMode"]["params"]["mode"]["constraints"]["enum"]

@handleNotSupported
def getActiveVentilationMode(self):
return self.service.getProperty("ventilation.operating.modes.active")["properties"]["value"]["value"]
return self.getVentilationModes()

@deprecated(reason="renamed, use activateVentilationMode", version="2.40.0")
def setActiveVentilationMode(self, mode):
""" Set the active mode
Parameters
Expand All @@ -138,35 +136,12 @@ def setActiveVentilationMode(self, mode):
result: json
json representation of the answer
"""
return self.service.setProperty("ventilation.operating.modes.active", "setMode", {'mode': mode})
return self.activateVentilationMode(mode)

@handleNotSupported
@deprecated(reason="renamed, use getVentilationPrograms", version="2.40.0")
def getAvailableVentilationPrograms(self):
available_programs = []
for program in ['basic', 'intensive', 'reduced', 'standard', 'standby', 'holidayAtHome', 'permanent']:
with suppress(PyViCareNotSupportedFeatureError):
if self.service.getProperty(f"ventilation.operating.programs.{program}") is not None:
available_programs.append(program)
return available_programs

@handleNotSupported
def getActiveVentilationProgram(self):
return self.service.getProperty("ventilation.operating.programs.active")["properties"]["value"]["value"]

def activateVentilationProgram(self, program):
""" Activate a ventilation program
NOTE
DEVICE_COMMUNICATION_ERROR can just mean that the program is already on
Parameters
----------
program : str
Returns
-------
result: json
json representation of the answer
"""
return self.service.setProperty(f"ventilation.operating.programs.{program}", "activate", {})
return self.getVentilationPrograms()

@handleNotSupported
def getDomesticHotWaterHysteresisUnit(self) -> str:
Expand Down
175 changes: 130 additions & 45 deletions PyViCare/PyViCareVentilationDevice.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from contextlib import suppress
from deprecated import deprecated

from PyViCare.PyViCareDevice import Device
from PyViCare.PyViCareUtils import (PyViCareNotSupportedFeatureError, handleAPICommandErrors, handleNotSupported)
Expand All @@ -12,13 +13,72 @@ class VentilationDevice(Device):
"""

@handleNotSupported
def getVentilationDemand(self) -> str:
return str(self.service.getProperty("ventilation.operating.state")["properties"]["demand"]["value"])

@handleNotSupported
def getVentilationReason(self) -> str:
return str(self.service.getProperty("ventilation.operating.state")["properties"]["reason"]["value"])

@handleNotSupported
def getVentilationModes(self) -> list[str]:
return list[str](self.service.getProperty("ventilation.operating.modes.active")["commands"]["setMode"]["params"]["mode"]["constraints"]["enum"])

@handleNotSupported
@deprecated(reason="renamed, use getVentilationModes", version="2.40.0")
def getAvailableModes(self):
return self.service.getProperty("ventilation.operating.modes.active")["commands"]["setMode"]["params"]["mode"]["constraints"]["enum"]
return self.getVentilationModes()

@handleNotSupported
def getVentilationMode(self, mode: str) -> bool:
return bool(self.service.getProperty(f"ventilation.operating.modes.{mode}")["properties"]["active"]["value"])

@handleNotSupported
def getActiveVentilationMode(self) -> str:
return str(self.service.getProperty("ventilation.operating.modes.active")["properties"]["value"]["value"])

@handleNotSupported
def getVentilationLevels(self) -> list[str]:
return list[str](self.service.getProperty("ventilation.operating.modes.permanent")["commands"]["setLevel"]["params"]["level"]["constraints"]["enum"])

@handleNotSupported
@deprecated(reason="renamed, use getVentilationLevels", version="2.40.0")
def getPermanentLevels(self) -> list[str]:
return list[str](self.getVentilationLevels())

@handleNotSupported
def getVentilationLevel(self) -> str:
return str(self.service.getProperty("ventilation.operating.state")["properties"]["level"]["value"])

@handleAPICommandErrors
def setVentilationLevel(self, level: str):
return self.service.setProperty("ventilation.operating.modes.permanent", "setLevel", {'level': level})

@handleAPICommandErrors
@deprecated(reason="renamed, use setVentilationLevel", version="2.40.0")
def setPermanentLevel(self, level: str):
return self.setVentilationLevel(level)

@handleNotSupported
@deprecated(reason="renamed, use getActiveVentilationMode", version="2.40.0")
def getActiveMode(self):
return self.service.getProperty("ventilation.operating.modes.active")["properties"]["value"]["value"]
return self.getActiveVentilationMode()

def activateVentilationMode(self, mode: str):
""" Set the active ventilation mode
Parameters
----------
mode : str
Valid mode can be obtained using getVentilationModes()
Returns
-------
result: json
json representation of the answer
"""
return self.service.setProperty("ventilation.operating.modes.active", "setMode", {'mode': mode})

@deprecated(reason="renamed, use activateVentilationMode", version="2.40.0")
def setActiveMode(self, mode):
""" Set the active mode
Parameters
Expand All @@ -31,10 +91,31 @@ def setActiveMode(self, mode):
result: json
json representation of the answer
"""
return self.service.setProperty("ventilation.operating.modes.active", "setMode", {'mode': mode})
return self.activateVentilationMode(mode)

@handleNotSupported
def getAvailablePrograms(self):
def getVentilationQuickmodes(self) -> list[str]:
available_quickmodes = []
for quickmode in ['comfort', 'eco', 'forcedLevelFour', 'holiday', 'standby', 'silent']:
with suppress(PyViCareNotSupportedFeatureError):
if self.service.getProperty(f"ventilation.quickmodes.{quickmode}") is not None:
available_quickmodes.append(quickmode)
return available_quickmodes

@handleNotSupported
def getVentilationQuickmode(self, quickmode: str) -> bool:
return bool(self.service.getProperty(f"ventilation.quickmodes.{quickmode}")["properties"]["active"]["value"])

@handleNotSupported
def activateVentilationQuickmode(self, quickmode: str) -> None:
self.service.setProperty(f"ventilation.quickmodes.{quickmode}", "activate", {})

@handleNotSupported
def deactivateVentilationQuickmode(self, quickmode: str) -> None:
self.service.setProperty(f"ventilation.quickmodes.{quickmode}", "deactivate", {})

@handleNotSupported
def getVentilationPrograms(self):
available_programs = []
for program in ['basic', 'intensive', 'reduced', 'standard', 'standby', 'holidayAtHome', 'permanent']:
with suppress(PyViCareNotSupportedFeatureError):
Expand All @@ -43,10 +124,20 @@ def getAvailablePrograms(self):
return available_programs

@handleNotSupported
def getActiveProgram(self):
@deprecated(reason="renamed, use getVentilationPrograms", version="2.40.0")
def getAvailablePrograms(self):
return self.getVentilationPrograms()

@handleNotSupported
def getActiveVentilationProgram(self):
return self.service.getProperty("ventilation.operating.programs.active")["properties"]["value"]["value"]

def activateProgram(self, program):
@handleNotSupported
@deprecated(reason="renamed, use getActiveVentilationProgram", version="2.40.0")
def getActiveProgram(self):
return self.getActiveVentilationProgram()

def activateVentilationProgram(self, program):
""" Activate a program
NOTE
DEVICE_COMMUNICATION_ERROR can just mean that the program is already on
Expand All @@ -61,7 +152,23 @@ def activateProgram(self, program):
"""
return self.service.setProperty(f"ventilation.operating.programs.{program}", "activate", {})

def deactivateProgram(self, program):
@deprecated(reason="renamed, use activateVentilationProgram", version="2.40.0")
def activateProgram(self, program):
""" Activate a program
NOTE
DEVICE_COMMUNICATION_ERROR can just mean that the program is already on
Parameters
----------
program : str
Returns
-------
result: json
json representation of the answer
"""
return self.activateVentilationProgram(program)

def deactivateVentilationProgram(self, program):
""" Deactivate a program
Parameters
----------
Expand All @@ -74,16 +181,22 @@ def deactivateProgram(self, program):
"""
return self.service.setProperty(f"ventilation.operating.programs.{program}", "deactivate", {})

@handleNotSupported
def getPermanentLevels(self) -> list[str]:
return list[str](self.service.getProperty("ventilation.operating.modes.permanent")["commands"]["setLevel"]["params"]["level"]["constraints"]["enum"])
@deprecated(reason="renamed, use deactivateVentilationProgram", version="2.40.0")
def deactivateProgram(self, program):
""" Deactivate a program
Parameters
----------
program : str
@handleAPICommandErrors
def setPermanentLevel(self, level: str):
return self.service.setProperty("ventilation.operating.modes.permanent", "setLevel", {'level': level})
Returns
-------
result: json
json representation of the answer
"""
return self.deactivateVentilationProgram(program)

@handleNotSupported
def getSchedule(self):
def getVentilationSchedule(self):
properties = self.service.getProperty("ventilation.schedule")["properties"]
return {
"active": properties["active"]["value"],
Expand All @@ -97,34 +210,6 @@ def getSchedule(self):
}

@handleNotSupported
def getVentilationDemand(self) -> str:
return str(self.service.getProperty("ventilation.operating.state")["properties"]["demand"]["value"])

@handleNotSupported
def getVentilationLevel(self) -> str:
return str(self.service.getProperty("ventilation.operating.state")["properties"]["level"]["value"])

@handleNotSupported
def getVentilationReason(self) -> str:
return str(self.service.getProperty("ventilation.operating.state")["properties"]["reason"]["value"])

@handleNotSupported
def getVentilationQuickmodes(self) -> list[str]:
available_quickmodes = []
for quickmode in ['comfort', 'eco', 'forcedLevelFour', 'holiday', 'standby', 'silent']:
with suppress(PyViCareNotSupportedFeatureError):
if self.service.getProperty(f"ventilation.quickmodes.{quickmode}") is not None:
available_quickmodes.append(quickmode)
return available_quickmodes

@handleNotSupported
def getVentilationQuickmode(self, quickmode: str) -> bool:
return bool(self.service.getProperty(f"ventilation.quickmodes.{quickmode}")["properties"]["active"]["value"])

@handleNotSupported
def activateVentilationQuickmode(self, quickmode: str) -> None:
self.service.setProperty(f"ventilation.quickmodes.{quickmode}", "activate", {})

@handleNotSupported
def deactivateVentilationQuickmode(self, quickmode: str) -> None:
self.service.setProperty(f"ventilation.quickmodes.{quickmode}", "deactivate", {})
@deprecated(reason="renamed, use getVentilationSchedule", version="2.40.0")
def getSchedule(self):
return self.getVentilationSchedule()
Loading

0 comments on commit 356605a

Please sign in to comment.