diff --git a/PyViCare/PyViCareHeatPump.py b/PyViCare/PyViCareHeatPump.py index 36701ed9..74da5477 100644 --- a/PyViCare/PyViCareHeatPump.py +++ b/PyViCare/PyViCareHeatPump.py @@ -45,11 +45,11 @@ def getInverter(self, inverter) -> Inverter: @handleNotSupported def getBufferMainTemperature(self): - return self.getProperty("heating.bufferCylinder.sensors.temperature.main")["properties"]['value']['value'] + return self.getProperty("heating.bufferCylinder.sensors.temperature.main")["properties"]["value"]["value"] @handleNotSupported def getBufferTopTemperature(self): - return self.getProperty("heating.bufferCylinder.sensors.temperature.top")["properties"]['value']['value'] + return self.getProperty("heating.bufferCylinder.sensors.temperature.top")["properties"]["value"]["value"] # Power consumption for Heating: @handleNotSupported @@ -325,6 +325,24 @@ def getSeasonalPerformanceFactorHeating(self) -> float: def getSeasonalPerformanceFactorTotal(self) -> float: return float(self.getProperty("heating.spf.total")["properties"]["value"]["value"]) + # COP (Coefficient of Performance) - instantaneous efficiency metrics + # Some devices expose COP instead of SPF + @handleNotSupported + def getCoefficientOfPerformanceHeating(self) -> float: + return float(self.getProperty("heating.cop.heating")["properties"]["value"]["value"]) + + @handleNotSupported + def getCoefficientOfPerformanceDHW(self) -> float: + return float(self.getProperty("heating.cop.dhw")["properties"]["value"]["value"]) + + @handleNotSupported + def getCoefficientOfPerformanceTotal(self) -> float: + return float(self.getProperty("heating.cop.total")["properties"]["value"]["value"]) + + @handleNotSupported + def getCoefficientOfPerformanceCooling(self) -> float: + return float(self.getProperty("heating.cop.cooling")["properties"]["value"]["value"]) + @handleNotSupported def getHeatingRodStarts(self) -> int: return int(self.getProperty("heating.heatingRod.statistics")["properties"]["starts"]["value"]) @@ -361,6 +379,157 @@ def getHeatingRodPowerConsumptionHeatingThisYear(self) -> float: def getHeatingRodPowerConsumptionTotalThisYear(self) -> float: return float(self.getProperty("heating.heatingRod.power.consumption.total")["properties"]["year"]["value"][0]) + # Heating rod power consumption summary for DHW: + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryDHWUnit(self) -> str: + return str(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["currentDay"]["unit"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryDHWCurrentDay(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["currentDay"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryDHWCurrentMonth(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["currentMonth"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryDHWCurrentYear(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["currentYear"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryDHWLastMonth(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["lastMonth"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryDHWLastSevenDays(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["lastSevenDays"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryDHWLastYear(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["lastYear"]["value"]) + + # Heating rod power consumption summary for Heating: + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryHeatingUnit(self) -> str: + return str(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["currentDay"]["unit"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryHeatingCurrentDay(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["currentDay"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryHeatingCurrentMonth(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["currentMonth"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryHeatingCurrentYear(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["currentYear"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryHeatingLastMonth(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["lastMonth"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryHeatingLastSevenDays(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["lastSevenDays"]["value"]) + + @handleNotSupported + def getHeatingRodPowerConsumptionSummaryHeatingLastYear(self) -> float: + return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["lastYear"]["value"]) + + # Heating rod runtime by level + @handleNotSupported + def getHeatingRodRuntimeLevelOne(self) -> int: + return int(self.getProperty("heating.heatingRod.runtime")["properties"]["levelOne"]["value"]) + + @handleNotSupported + def getHeatingRodRuntimeLevelTwo(self) -> int: + return int(self.getProperty("heating.heatingRod.runtime")["properties"]["levelTwo"]["value"]) + + @handleNotSupported + def getHeatingRodRuntimeLevelOneUnit(self) -> str: + return str(self.getProperty("heating.heatingRod.runtime")["properties"]["levelOne"]["unit"]) + + # Additional pressure sensors (refrigerant circuit) + @handleNotSupported + def getHotGasPressure(self) -> float: + return float(self.getProperty("heating.sensors.pressure.hotGas")["properties"]["value"]["value"]) + + @handleNotSupported + def getHotGasPressureUnit(self) -> str: + return str(self.getProperty("heating.sensors.pressure.hotGas")["properties"]["value"]["unit"]) + + @handleNotSupported + def getSuctionGasPressure(self) -> float: + return float(self.getProperty("heating.sensors.pressure.suctionGas")["properties"]["value"]["value"]) + + @handleNotSupported + def getSuctionGasPressureUnit(self) -> str: + return str(self.getProperty("heating.sensors.pressure.suctionGas")["properties"]["value"]["unit"]) + + # Additional temperature sensors (refrigerant circuit) + @handleNotSupported + def getHotGasTemperature(self) -> float: + return float(self.getProperty("heating.sensors.temperature.hotGas")["properties"]["value"]["value"]) + + @handleNotSupported + def getHotGasTemperatureUnit(self) -> str: + return str(self.getProperty("heating.sensors.temperature.hotGas")["properties"]["value"]["unit"]) + + @handleNotSupported + def getLiquidGasTemperature(self) -> float: + return float(self.getProperty("heating.sensors.temperature.liquidGas")["properties"]["value"]["value"]) + + @handleNotSupported + def getLiquidGasTemperatureUnit(self) -> str: + return str(self.getProperty("heating.sensors.temperature.liquidGas")["properties"]["value"]["unit"]) + + @handleNotSupported + def getSuctionGasTemperature(self) -> float: + return float(self.getProperty("heating.sensors.temperature.suctionGas")["properties"]["value"]["value"]) + + @handleNotSupported + def getSuctionGasTemperatureUnit(self) -> str: + return str(self.getProperty("heating.sensors.temperature.suctionGas")["properties"]["value"]["unit"]) + + # Main ECU runtime + @handleNotSupported + def getMainECURuntime(self) -> int: + return int(self.getProperty("heating.device.mainECU")["properties"]["runtime"]["value"]) + + @handleNotSupported + def getMainECURuntimeUnit(self) -> str: + return str(self.getProperty("heating.device.mainECU")["properties"]["runtime"]["unit"]) + + # Configuration values + @handleNotSupported + def getConfigurationBufferTemperatureMax(self) -> float: + return float(self.getProperty("heating.configuration.buffer.temperature.max")["properties"]["value"]["value"]) + + @handleNotSupported + def getConfigurationBufferTemperatureMaxUnit(self) -> str: + return str(self.getProperty("heating.configuration.buffer.temperature.max")["properties"]["value"]["unit"]) + + @handleNotSupported + def getConfigurationOutsideTemperatureDampingFactor(self) -> int: + return int(self.getProperty("heating.configuration.temperature.outside.DampingFactor")["properties"]["value"]["value"]) + + @handleNotSupported + def getConfigurationOutsideTemperatureDampingFactorUnit(self) -> str: + return str(self.getProperty("heating.configuration.temperature.outside.DampingFactor")["properties"]["value"]["unit"]) + + @handleNotSupported + def getConfigurationHeatingRodDHWApproved(self) -> bool: + return bool(self.getProperty("heating.configuration.heatingRod.dhw")["properties"]["useApproved"]["value"]) + + @handleNotSupported + def getConfigurationHeatingRodHeatingApproved(self) -> bool: + return bool(self.getProperty("heating.configuration.heatingRod.heating")["properties"]["useApproved"]["value"]) + + @handleNotSupported + def getConfigurationDHWHeaterApproved(self) -> bool: + return bool(self.getProperty("heating.configuration.dhwHeater")["properties"]["useApproved"]["value"]) + # Cooling circuits @property def coolingCircuits(self) -> List[CoolingCircuit]: @@ -395,6 +564,7 @@ def getReverseActive(self) -> bool: return bool(self.getProperty(f"heating.coolingCircuits.{self.circuit}.reverse")["properties"]["active"]["value"]) + class Compressor(HeatingDeviceWithComponent): @property @@ -409,25 +579,45 @@ def getStarts(self): def getHours(self): return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hours"]["value"] - @handleNotSupported def getHoursLoadClass1(self): - return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassOne"]["value"] + """Get hours in load class 1. Tries 'statistics' path first, then 'statistics.load'.""" + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassOne"]["value"] + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassOne"]["value"] + raise PyViCareNotSupportedFeatureError("getHoursLoadClass1") - @handleNotSupported def getHoursLoadClass2(self): - return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassTwo"]["value"] + """Get hours in load class 2. Tries 'statistics' path first, then 'statistics.load'.""" + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassTwo"]["value"] + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassTwo"]["value"] + raise PyViCareNotSupportedFeatureError("getHoursLoadClass2") - @handleNotSupported def getHoursLoadClass3(self): - return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassThree"]["value"] + """Get hours in load class 3. Tries 'statistics' path first, then 'statistics.load'.""" + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassThree"]["value"] + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassThree"]["value"] + raise PyViCareNotSupportedFeatureError("getHoursLoadClass3") - @handleNotSupported def getHoursLoadClass4(self): - return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassFour"]["value"] + """Get hours in load class 4. Tries 'statistics' path first, then 'statistics.load'.""" + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassFour"]["value"] + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassFour"]["value"] + raise PyViCareNotSupportedFeatureError("getHoursLoadClass4") - @handleNotSupported def getHoursLoadClass5(self): - return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassFive"]["value"] + """Get hours in load class 5. Tries 'statistics' path first, then 'statistics.load'.""" + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassFive"]["value"] + with suppress(KeyError): + return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassFive"]["value"] + raise PyViCareNotSupportedFeatureError("getHoursLoadClass5") @handleNotSupported def getActive(self): @@ -437,6 +627,24 @@ def getActive(self): def getPhase(self): return self.getProperty(f"heating.compressors.{self.compressor}")["properties"]["phase"]["value"] + @handleNotSupported + def getPower(self) -> float: + # Returns the nominal/maximum power of the compressor in kW + return float(self.getProperty(f"heating.compressors.{self.compressor}.power")["properties"]["value"]["value"]) + + @handleNotSupported + def getPowerUnit(self) -> str: + return str(self.getProperty(f"heating.compressors.{self.compressor}.power")["properties"]["value"]["unit"]) + + @handleNotSupported + def getModulation(self) -> int: + # Returns the current compressor modulation/power level as percentage (0-100) + return int(self.getProperty(f"heating.compressors.{self.compressor}.sensors.power")["properties"]["value"]["value"]) + + @handleNotSupported + def getModulationUnit(self) -> str: + return str(self.getProperty(f"heating.compressors.{self.compressor}.sensors.power")["properties"]["value"]["unit"]) + @handleNotSupported def getSpeed(self) -> int: return int(self.getProperty(f"heating.compressors.{self.compressor}.speed.current")["properties"]["value"]["value"]) diff --git a/PyViCare/PyViCareHeatingDevice.py b/PyViCare/PyViCareHeatingDevice.py index 4cd12d8e..de31df05 100644 --- a/PyViCare/PyViCareHeatingDevice.py +++ b/PyViCare/PyViCareHeatingDevice.py @@ -368,6 +368,15 @@ def getReturnTemperaturePrimaryCircuit(self): return self.getProperty("heating.primaryCircuit.sensors.temperature.return")["properties"]["value"][ "value"] + @handleNotSupported + def getPrimaryCircuitPumpRotation(self) -> float: + """Get primary circuit pump rotation/speed as percentage.""" + return float(self.getProperty("heating.primaryCircuit.sensors.rotation")["properties"]["value"]["value"]) + + @handleNotSupported + def getPrimaryCircuitPumpRotationUnit(self): + return self.getProperty("heating.primaryCircuit.sensors.rotation")["properties"]["value"]["unit"] + @handleNotSupported def getSupplyTemperatureSecondaryCircuit(self): return self.getProperty("heating.secondaryCircuit.sensors.temperature.supply")["properties"]["value"][ @@ -548,6 +557,15 @@ def getSupplyTemperature(self): self.getProperty(f"heating.circuits.{self.circuit}.sensors.temperature.supply")["properties"][ "value"]["value"] + @handleNotSupported + def getTargetTemperature(self) -> float: + """Get the circuit target temperature.""" + return float(self.getProperty(f"heating.circuits.{self.circuit}.temperature")["properties"]["value"]["value"]) + + @handleNotSupported + def getTargetTemperatureUnit(self): + return self.getProperty(f"heating.circuits.{self.circuit}.temperature")["properties"]["value"]["unit"] + @handleNotSupported def getRoomTemperature(self): return self.getProperty(f"heating.circuits.{self.circuit}.sensors.temperature.room")["properties"][ diff --git a/tests/test_TestForMissingProperties.py b/tests/test_TestForMissingProperties.py index 7b06e748..c6fa396f 100644 --- a/tests/test_TestForMissingProperties.py +++ b/tests/test_TestForMissingProperties.py @@ -36,6 +36,15 @@ def test_deprecatedProperties(self): 'ventilation.operating.programs.levelTwo', 'ventilation.operating.programs.forcedLevelFour', 'ventilation.operating.programs.silent', + # Alternative naming conventions used as fallback for device compatibility + 'heating.buffer.sensors.temperature.main', + 'heating.buffer.sensors.temperature.top', + 'heating.dhw.sensors.temperature.hotWaterStorage', + 'heating.dhw.sensors.temperature.hotWaterStorage.top', + 'heating.dhw.sensors.temperature.hotWaterStorage.bottom', + 'heating.dhw.sensors.temperature.hotWaterStorage.middle', + 'heating.dhw.sensors.temperature.hotWaterStorage.midBottom', + 'heating.cop.green', # deprecated, replaced by heating.cop.photovoltaic ] all_features = self.read_all_deprecated_features() @@ -201,12 +210,11 @@ def test_missingProperties(self): 'heating.compressors.0.sensors.power', 'heating.compressors.0.statistics.load', 'heating.configuration.buffer.temperature.max', - 'heating.configuration.dhwHeater', 'heating.configuration.flow.temperature.max', 'heating.configuration.flow.temperature.min', 'heating.cop.cooling', 'heating.cop.dhw', - 'heating.cop.green', + 'heating.cop.green', # deprecated, replaced by heating.cop.photovoltaic 'heating.cop.heating', 'heating.cop.total', 'heating.heatingRod.heatTarget', @@ -217,8 +225,6 @@ def test_missingProperties(self): 'heating.sensors.temperature.hotGas', 'heating.sensors.temperature.liquidGas', 'heating.sensors.temperature.suctionGas', - 'heating.heatingRod.power.consumption.summary.dhw', - 'heating.heatingRod.power.consumption.summary.heating', 'heating.heatingRod.status', 'heating.scop.dhw', # deprecated 'heating.scop.heating', # deprecated @@ -362,6 +368,7 @@ def test_unverifiedProperties(self): for match in re.findall(r'getProperty\(\s*?f?"(.*)"\s*?\)', all_python_files[python]): feature_name = re.sub(r'{(self\.)?(circuit|burner|compressor|condensor|evaporator|inverter)}', '0', match) feature_name = re.sub(r'{burner}', '0', feature_name) + feature_name = re.sub(r'{circuit}', '0', feature_name) # for local variable in loops feature_name = re.sub(r'\.{(quickmode|mode|program|active_program)}', '', feature_name) used_features.append(feature_name) diff --git a/tests/test_Vitocal250A.py b/tests/test_Vitocal250A.py index 227ab56e..5b051a6d 100644 --- a/tests/test_Vitocal250A.py +++ b/tests/test_Vitocal250A.py @@ -226,13 +226,41 @@ def test_getSeasonalPerformanceFactor(self): self.assertEqual(self.device.getSeasonalPerformanceFactorTotal(), 3.9) def test_getHeatingRod(self): - # self.assertEqual(self.device.getHeatingRodHeatProductionCurrent(), 0) # not in dump - # self.assertEqual(self.device.getHeatingRodPowerConsumptionCurrent(), 0) # not in dump - # self.assertEqual(self.device.getHeatingRodPowerConsumptionDHWThisYear(), 0) - # self.assertEqual(self.device.getHeatingRodPowerConsumptionHeatingThisYear(), 0) self.assertEqual(self.device.getHeatingRodStarts(), 314) self.assertEqual(self.device.getHeatingRodHours(), 31) + def test_getHeatingRodPowerConsumptionSummaryDHW(self): + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryDHWUnit(), "kilowattHour") + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryDHWCurrentDay(), 0) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryDHWCurrentMonth(), 0) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryDHWCurrentYear(), 3.3) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryDHWLastMonth(), 0) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryDHWLastSevenDays(), 0) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryDHWLastYear(), 28) + + def test_getHeatingRodPowerConsumptionSummaryHeating(self): + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryHeatingUnit(), "kilowattHour") + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryHeatingCurrentDay(), 0) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryHeatingCurrentMonth(), 0) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryHeatingCurrentYear(), 29.5) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryHeatingLastMonth(), 0) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryHeatingLastSevenDays(), 0) + self.assertEqual( + self.device.getHeatingRodPowerConsumptionSummaryHeatingLastYear(), 53.6) + def test_inverter_getCurrent(self): self.assertEqual(self.device.inverters[0].getCurrent(), 0) diff --git a/tests/test_Vitocal300G.py b/tests/test_Vitocal300G.py index 59434471..e603e6a5 100644 --- a/tests/test_Vitocal300G.py +++ b/tests/test_Vitocal300G.py @@ -9,9 +9,47 @@ def setUp(self): self.service = ViCareServiceMock('response/Vitocal300G_CU401B.json') self.device = HeatPump(self.service) + # COP (Coefficient of Performance) tests + def test_getCoefficientOfPerformanceHeating(self): + self.assertAlmostEqual( + self.device.getCoefficientOfPerformanceHeating(), 4.8) + + def test_getCoefficientOfPerformanceDHW(self): + self.assertAlmostEqual( + self.device.getCoefficientOfPerformanceDHW(), 4.0) + + def test_getCoefficientOfPerformanceTotal(self): + self.assertAlmostEqual( + self.device.getCoefficientOfPerformanceTotal(), 4.7) + + def test_getCoefficientOfPerformanceCooling(self): + self.assertAlmostEqual( + self.device.getCoefficientOfPerformanceCooling(), 0.0) + + # Compressor power tests + def test_compressor_getPower(self): + self.assertAlmostEqual( + self.device.compressors[0].getPower(), 12.0) + + def test_compressor_getPowerUnit(self): + self.assertEqual( + self.device.compressors[0].getPowerUnit(), "kilowatt") + + def test_compressor_getModulation(self): + self.assertEqual( + self.device.compressors[0].getModulation(), 100) + + def test_compressor_getModulationUnit(self): + self.assertEqual( + self.device.compressors[0].getModulationUnit(), "percent") + + # Compressor statistics tests def test_compressor_getActive(self): self.assertEqual(self.device.compressors[0].getActive(), True) + def test_compressor_getPhase(self): + self.assertEqual(self.device.compressors[0].getPhase(), "heating") + def test_compressor_getHours(self): self.assertAlmostEqual( self.device.compressors[0].getHours(), 942.4) @@ -20,66 +58,197 @@ def test_compressor_getStarts(self): self.assertAlmostEqual( self.device.compressors[0].getStarts(), 363) - # Load class tests require fallback logic from PR #689 - # Data is in statistics.load instead of statistics - @unittest.skip("Requires PR #689 for statistics.load fallback") + # Load class tests - use statistics.load fallback path def test_compressor_getHoursLoadClass1(self): self.assertAlmostEqual( self.device.compressors[0].getHoursLoadClass1(), 5) - @unittest.skip("Requires PR #689 for statistics.load fallback") def test_compressor_getHoursLoadClass2(self): self.assertAlmostEqual( self.device.compressors[0].getHoursLoadClass2(), 233) - @unittest.skip("Requires PR #689 for statistics.load fallback") def test_compressor_getHoursLoadClass3(self): self.assertAlmostEqual( self.device.compressors[0].getHoursLoadClass3(), 448) - @unittest.skip("Requires PR #689 for statistics.load fallback") def test_compressor_getHoursLoadClass4(self): self.assertAlmostEqual( self.device.compressors[0].getHoursLoadClass4(), 249) - @unittest.skip("Requires PR #689 for statistics.load fallback") def test_compressor_getHoursLoadClass5(self): self.assertAlmostEqual( self.device.compressors[0].getHoursLoadClass5(), 3) - # This device only has circuit "1" enabled (circuits[0] in the list) - def test_getHeatingCurveSlope(self): + # Compressor sensor tests + def test_compressor_getInletPressure(self): self.assertAlmostEqual( - self.device.circuits[0].getHeatingCurveSlope(), 1.0) + self.device.compressors[0].getInletPressure(), 8.7) - def test_getHeatingCurveShift(self): + def test_compressor_getInletTemperature(self): self.assertAlmostEqual( - self.device.circuits[0].getHeatingCurveShift(), 2) + self.device.compressors[0].getInletTemperature(), 7.1) + + def test_compressor_getOutletTemperature(self): + self.assertAlmostEqual( + self.device.compressors[0].getOutletTemperature(), 79.5) + + def test_compressor_getOverheatTemperature(self): + self.assertAlmostEqual( + self.device.compressors[0].getOverheatTemperature(), 4.0) + + # General device tests + def test_getOutsideTemperature(self): + self.assertAlmostEqual( + self.device.getOutsideTemperature(), 4.1) def test_getReturnTemperature(self): self.assertAlmostEqual(self.device.getReturnTemperature(), 35.8) + def test_getSupplyTemperaturePrimaryCircuit(self): + self.assertAlmostEqual( + self.device.getSupplyTemperaturePrimaryCircuit(), 8.7) + def test_getReturnTemperaturePrimaryCircuit(self): self.assertAlmostEqual(self.device.getReturnTemperaturePrimaryCircuit(), 4.9) - def test_getSupplyTemperaturePrimaryCircuit(self): + # DHW tests + def test_getDomesticHotWaterStorageTemperature(self): self.assertAlmostEqual( - self.device.getSupplyTemperaturePrimaryCircuit(), 8.7) + self.device.getDomesticHotWaterStorageTemperature(), 52.4) + + def test_getDomesticHotWaterConfiguredTemperature(self): + self.assertAlmostEqual( + self.device.getDomesticHotWaterConfiguredTemperature(), 50.0) + + def test_getDomesticHotWaterCirculationPumpActive(self): + self.assertEqual( + self.device.getDomesticHotWaterCirculationPumpActive(), False) + + def test_getHotWaterStorageTemperatureTop(self): + self.assertAlmostEqual( + self.device.getHotWaterStorageTemperatureTop(), 52.4) + + # Buffer tests + def test_getBufferMainTemperature(self): + self.assertAlmostEqual( + self.device.getBufferMainTemperature(), 36.2) + + def test_getBufferTopTemperature(self): + self.assertAlmostEqual( + self.device.getBufferTopTemperature(), 36.2) + + # Circuit tests + def test_circuit_getSupplyTemperature(self): + self.assertAlmostEqual( + self.device.circuits[0].getSupplyTemperature(), 36.1) + + def test_getHeatingCurveSlope(self): + self.assertAlmostEqual( + self.device.circuits[0].getHeatingCurveSlope(), 1.0) + + def test_getHeatingCurveShift(self): + self.assertAlmostEqual( + self.device.circuits[0].getHeatingCurveShift(), 2) + + def test_circuit_getActiveMode(self): + self.assertEqual( + self.device.circuits[0].getActiveMode(), "dhwAndHeating") + + def test_circuit_getActiveProgram(self): + self.assertEqual( + self.device.circuits[0].getActiveProgram(), "normal") + + def test_circuit_getTargetTemperature(self): + self.assertAlmostEqual( + self.device.circuits[0].getTargetTemperature(), 40) def test_getPrograms(self): expected_programs = ['comfort', 'eco', 'fixed', 'normal', 'reduced', 'standby'] self.assertListEqual( self.device.circuits[0].getPrograms(), expected_programs) - # Available modes vary by device configuration (e.g., cooling enabled) def test_getModes(self): expected_modes = ['dhw', 'dhwAndHeating', 'standby'] self.assertListEqual( self.device.circuits[0].getModes(), expected_modes) - def test_getDomesticHotWaterCirculationPumpActive(self): + # Primary circuit pump tests + def test_getPrimaryCircuitPumpRotation(self): + self.assertAlmostEqual( + self.device.getPrimaryCircuitPumpRotation(), 80) + + def test_getPrimaryCircuitPumpRotationUnit(self): self.assertEqual( - self.device.getDomesticHotWaterCirculationPumpActive(), False) + self.device.getPrimaryCircuitPumpRotationUnit(), "percent") + + # Pressure sensor tests (refrigerant circuit) + def test_getHotGasPressure(self): + self.assertAlmostEqual( + self.device.getHotGasPressure(), 28.1) + + def test_getHotGasPressureUnit(self): + self.assertEqual( + self.device.getHotGasPressureUnit(), "bar") + + def test_getSuctionGasPressure(self): + self.assertAlmostEqual( + self.device.getSuctionGasPressure(), 8.7) + + def test_getSuctionGasPressureUnit(self): + self.assertEqual( + self.device.getSuctionGasPressureUnit(), "bar") + + # Temperature sensor tests (refrigerant circuit) + def test_getHotGasTemperature(self): + self.assertAlmostEqual( + self.device.getHotGasTemperature(), 79.5) + + def test_getLiquidGasTemperature(self): + self.assertAlmostEqual( + self.device.getLiquidGasTemperature(), 36) + + def test_getSuctionGasTemperature(self): + self.assertAlmostEqual( + self.device.getSuctionGasTemperature(), 7.1) + + # Main ECU runtime test + def test_getMainECURuntime(self): + self.assertEqual( + self.device.getMainECURuntime(), 7768472) + + def test_getMainECURuntimeUnit(self): + self.assertEqual( + self.device.getMainECURuntimeUnit(), "seconds") + + # Heating rod runtime tests + def test_getHeatingRodRuntimeLevelOne(self): + self.assertEqual( + self.device.getHeatingRodRuntimeLevelOne(), 886682) + + def test_getHeatingRodRuntimeLevelTwo(self): + self.assertEqual( + self.device.getHeatingRodRuntimeLevelTwo(), 287877) + + # Configuration tests + def test_getConfigurationBufferTemperatureMax(self): + self.assertAlmostEqual( + self.device.getConfigurationBufferTemperatureMax(), 65) + + def test_getConfigurationOutsideTemperatureDampingFactor(self): + self.assertEqual( + self.device.getConfigurationOutsideTemperatureDampingFactor(), 180) + + def test_getConfigurationHeatingRodDHWApproved(self): + self.assertEqual( + self.device.getConfigurationHeatingRodDHWApproved(), False) + + def test_getConfigurationHeatingRodHeatingApproved(self): + self.assertEqual( + self.device.getConfigurationHeatingRodHeatingApproved(), False) + + def test_getConfigurationDHWHeaterApproved(self): + self.assertEqual( + self.device.getConfigurationDHWHeaterApproved(), True) # Cooling circuit tests def test_getAvailableCoolingCircuits(self):