PyViCare 2.55.1__tar.gz → 2.57.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. {pyvicare-2.55.1 → pyvicare-2.57.0}/PKG-INFO +1 -1
  2. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCare.py +1 -1
  3. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareAbstractOAuthManager.py +6 -0
  4. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareCachedService.py +13 -3
  5. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareDeviceConfig.py +29 -4
  6. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareFuelCell.py +16 -16
  7. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareGateway.py +2 -2
  8. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareHeatPump.py +83 -1
  9. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareHeatingDevice.py +14 -0
  10. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareUtils.py +12 -0
  11. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareVentilationDevice.py +20 -0
  12. {pyvicare-2.55.1 → pyvicare-2.57.0}/pyproject.toml +3 -2
  13. {pyvicare-2.55.1 → pyvicare-2.57.0}/LICENSE +0 -0
  14. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/Feature.py +0 -0
  15. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareBrowserOAuthManager.py +0 -0
  16. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareDevice.py +0 -0
  17. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareElectricalEnergySystem.py +0 -0
  18. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareFloorHeating.py +0 -0
  19. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareGazBoiler.py +0 -0
  20. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareHeatCurveCalculation.py +0 -0
  21. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareHybrid.py +0 -0
  22. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareOAuthManager.py +0 -0
  23. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareOilBoiler.py +0 -0
  24. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCarePelletsBoiler.py +0 -0
  25. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareRadiatorActuator.py +0 -0
  26. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareRepeater.py +0 -0
  27. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareRoomSensor.py +0 -0
  28. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/PyViCareService.py +0 -0
  29. {pyvicare-2.55.1 → pyvicare-2.57.0}/PyViCare/__init__.py +0 -0
  30. {pyvicare-2.55.1 → pyvicare-2.57.0}/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyViCare
3
- Version: 2.55.1
3
+ Version: 2.57.0
4
4
  Summary: Library to communicate with the Viessmann ViCare API.
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -61,7 +61,7 @@ class PyViCare:
61
61
 
62
62
  logger.info("Device found: %s", device.modelId)
63
63
 
64
- yield PyViCareDeviceConfig(service, device.id, device.modelId, device.status)
64
+ yield PyViCareDeviceConfig(service, device.id, device.modelId, device.status, device.deviceType, device.roles)
65
65
 
66
66
 
67
67
  class DictWrap(object):
@@ -7,6 +7,7 @@ from authlib.integrations.requests_client import OAuth2Session
7
7
 
8
8
  from PyViCare import Feature
9
9
  from PyViCare.PyViCareUtils import (PyViCareCommandError,
10
+ PyViCareDeviceCommunicationError,
10
11
  PyViCareInternalServerError,
11
12
  PyViCareRateLimitError)
12
13
 
@@ -39,6 +40,7 @@ class AbstractViCareOAuthManager:
39
40
  logger.debug("Response to get request: %s", response)
40
41
  self.__handle_expired_token(response)
41
42
  self.__handle_rate_limit(response)
43
+ self.__handle_device_communication_error(response)
42
44
  self.__handle_server_error(response)
43
45
  return response
44
46
  except TokenExpiredError:
@@ -59,6 +61,10 @@ class AbstractViCareOAuthManager:
59
61
  if ("statusCode" in response and response["statusCode"] == 429):
60
62
  raise PyViCareRateLimitError(response)
61
63
 
64
+ def __handle_device_communication_error(self, response):
65
+ if ("errorType" in response and response["errorType"] == "DEVICE_COMMUNICATION_ERROR"):
66
+ raise PyViCareDeviceCommunicationError(response)
67
+
62
68
  def __handle_server_error(self, response):
63
69
  if ("statusCode" in response and response["statusCode"] >= 500):
64
70
  raise PyViCareInternalServerError(response)
@@ -5,7 +5,10 @@ from typing import Any, List
5
5
  from PyViCare.PyViCareAbstractOAuthManager import AbstractViCareOAuthManager
6
6
  from PyViCare.PyViCareService import (ViCareDeviceAccessor, ViCareService,
7
7
  readFeature)
8
- from PyViCare.PyViCareUtils import PyViCareInvalidDataError, ViCareTimer
8
+ from PyViCare.PyViCareUtils import (PyViCareDeviceCommunicationError,
9
+ PyViCareInvalidDataError,
10
+ PyViCareInternalServerError,
11
+ ViCareTimer)
9
12
 
10
13
  logger = logging.getLogger('ViCare')
11
14
  logger.addHandler(logging.NullHandler())
@@ -33,13 +36,20 @@ class ViCareCachedService(ViCareService):
33
36
  def __get_or_update_cache(self):
34
37
  with self.__lock:
35
38
  if self.is_cache_invalid():
36
- # we always sett the cache time before we fetch the data
39
+ # we always set the cache time before we fetch the data
37
40
  # to avoid consuming all the api calls if the api is down
38
41
  # see https://github.com/home-assistant/core/issues/67052
39
42
  # we simply return the old cache in this case
40
43
  self.__cacheTime = ViCareTimer().now()
41
44
 
42
- data = self.fetch_all_features()
45
+ try:
46
+ data = self.fetch_all_features()
47
+ except (PyViCareDeviceCommunicationError, PyViCareInternalServerError) as e:
48
+ if self.__cache is not None:
49
+ logger.warning("API error, returning stale cache: %s", e)
50
+ return self.__cache
51
+ raise
52
+
43
53
  if "data" not in data:
44
54
  logger.error("Missing 'data' property when fetching data.")
45
55
  raise PyViCareInvalidDataError(data)
@@ -22,11 +22,14 @@ logger.addHandler(logging.NullHandler())
22
22
 
23
23
 
24
24
  class PyViCareDeviceConfig:
25
- def __init__(self, service, device_id, device_model, status):
25
+ # pylint: disable=too-many-arguments,too-many-positional-arguments
26
+ def __init__(self, service, device_id, device_model, status, device_type=None, roles=None):
26
27
  self.service = service
27
28
  self.device_id = device_id
28
29
  self.device_model = device_model
29
30
  self.status = status
31
+ self.device_type = device_type
32
+ self.roles = roles if roles is not None else []
30
33
 
31
34
  def asGeneric(self):
32
35
  return HeatingDevice(self.service)
@@ -85,6 +88,15 @@ class PyViCareDeviceConfig:
85
88
  def isOnline(self):
86
89
  return self.status == "Online"
87
90
 
91
+ def getDeviceType(self):
92
+ return self.device_type
93
+
94
+ def getRoles(self):
95
+ return self.roles
96
+
97
+ def isGateway(self):
98
+ return self.service._isGateway() # pylint: disable=protected-access
99
+
88
100
  # see: https://vitodata300.viessmann.com/vd300/ApplicationHelp/VD300/1031_de_DE/Ger%C3%A4teliste.html
89
101
  def asAutoDetectDevice(self):
90
102
  device_types = [
@@ -122,12 +134,25 @@ class PyViCareDeviceConfig:
122
134
  return self.service.fetch_all_features()
123
135
 
124
136
  def dump_secure(self, flat=False):
137
+ raw_data = self.get_raw_json()
138
+ device_info = {
139
+ "id": self.device_id,
140
+ "modelId": self.device_model,
141
+ "type": self.device_type,
142
+ "status": self.status,
143
+ "roles": self.roles
144
+ }
145
+ output = {
146
+ "device": device_info,
147
+ "data": raw_data['data']
148
+ }
149
+
125
150
  if flat:
126
- inner = ',\n'.join([json.dumps(x, sort_keys=True) for x in self.get_raw_json()['data']])
127
- outer = json.dumps({'data': ['placeholder']}, indent=0)
151
+ inner = ',\n'.join([json.dumps(x, sort_keys=True) for x in output['data']])
152
+ outer = json.dumps({'device': output['device'], 'data': ['placeholder']}, indent=0, sort_keys=True)
128
153
  dumpJSON = outer.replace('"placeholder"', inner)
129
154
  else:
130
- dumpJSON = json.dumps(self.get_raw_json(), indent=4, sort_keys=True)
155
+ dumpJSON = json.dumps(output, indent=4, sort_keys=True)
131
156
 
132
157
  def repl(m):
133
158
  return m.group(1) + ('#' * len(m.group(2))) + m.group(3)
@@ -192,9 +192,9 @@ class FuelCell(HeatingDevice):
192
192
  return self.getProperty("heating.fuelCell.power.production")["properties"]["year"]["value"][0]
193
193
 
194
194
  @handleNotSupported
195
- def getFuelCellOperatingPhase(self):
195
+ def getFuelCellOperatingPhase(self) -> str:
196
196
  # Returns current operating phase as string, e.g. "standby" or "generation"
197
- return self.getProperty("heating.fuelCell.operating.phase")["properties"]["value"]["value"]
197
+ return str(self.getProperty("fuelCell.operating.phase")["properties"]["value"]["value"])
198
198
 
199
199
  @handleNotSupported
200
200
  def getFuelCellPowerProductionCurrentUnit(self):
@@ -257,39 +257,39 @@ class FuelCell(HeatingDevice):
257
257
  return self.getProperty("heating.power.sold.cumulative")["properties"]["value"]["value"]
258
258
 
259
259
  @handleNotSupported
260
- def getFuelCellFlowReturnTemperatureUnit(self):
260
+ def getFuelCellFlowReturnTemperatureUnit(self) -> str:
261
261
  # Returns flow return temperature unit, e.g. "celsius"
262
- return self.getProperty("heating.fuelCell.sensors.temperature.return")["properties"]["value"]["unit"]
262
+ return str(self.getProperty("fuelCell.sensors.temperature.return")["properties"]["value"]["unit"])
263
263
 
264
264
  @handleNotSupported
265
- def getFuelCellFlowReturnTemperature(self):
265
+ def getFuelCellFlowReturnTemperature(self) -> float:
266
266
  # Returns flow return temperature at the fuel cell as float
267
- return self.getProperty("heating.fuelCell.sensors.temperature.return")["properties"]["value"]["value"]
267
+ return float(self.getProperty("fuelCell.sensors.temperature.return")["properties"]["value"]["value"])
268
268
 
269
269
  @handleNotSupported
270
- def getFuelCellFlowSupplyTemperatureUnit(self):
270
+ def getFuelCellFlowSupplyTemperatureUnit(self) -> str:
271
271
  # Returns flow supply temperature unit, e.g. "celsius"
272
- return self.getProperty("heating.fuelCell.sensors.temperature.supply")["properties"]["value"]["unit"]
272
+ return str(self.getProperty("fuelCell.sensors.temperature.supply")["properties"]["value"]["unit"])
273
273
 
274
274
  @handleNotSupported
275
- def getFuelCellFlowSupplyTemperature(self):
275
+ def getFuelCellFlowSupplyTemperature(self) -> float:
276
276
  # Returns flow supply temperature at the fuel cell as float
277
- return self.getProperty("heating.fuelCell.sensors.temperature.supply")["properties"]["value"]["value"]
277
+ return float(self.getProperty("fuelCell.sensors.temperature.supply")["properties"]["value"]["value"])
278
278
 
279
279
  @handleNotSupported
280
- def getFuelCellOperationHours(self):
280
+ def getFuelCellOperationHours(self) -> int:
281
281
  # Returns the operation hours of the fuel cell
282
- return self.getProperty("heating.fuelCell.statistics")["properties"]["operationHours"]["value"]
282
+ return int(self.getProperty("fuelCell.statistics")["properties"]["operationHours"]["value"])
283
283
 
284
284
  @handleNotSupported
285
- def getFuelCellProductionHours(self):
285
+ def getFuelCellProductionHours(self) -> int:
286
286
  # Returns the production hours of the fuel cell
287
- return self.getProperty("heating.fuelCell.statistics")["properties"]["productionHours"]["value"]
287
+ return int(self.getProperty("fuelCell.statistics")["properties"]["productionHours"]["value"])
288
288
 
289
289
  @handleNotSupported
290
- def getFuelCellProductionStarts(self):
290
+ def getFuelCellProductionStarts(self) -> int:
291
291
  # Returns the number of production starts of the fuel cell
292
- return self.getProperty("heating.fuelCell.statistics")["properties"]["productionStarts"]["value"]
292
+ return int(self.getProperty("fuelCell.statistics")["properties"]["productionStarts"]["value"])
293
293
 
294
294
  @handleNotSupported
295
295
  def getFuelCellGasConsumptionUnit(self):
@@ -9,5 +9,5 @@ class Gateway(Device):
9
9
  return self.getProperty("gateway.devices")["gatewayId"]
10
10
 
11
11
  @handleNotSupported
12
- def getWifiSignalStrength(self):
13
- return self.getProperty("gateway.wifi")["properties"]["strength"]["value"]
12
+ def getWifiSignalStrength(self) -> int:
13
+ return int(self.getProperty("gateway.wifi")["properties"]["strength"]["value"])
@@ -1,9 +1,11 @@
1
1
  from __future__ import annotations
2
+ from contextlib import suppress
2
3
  from typing import Any, List
3
4
  from deprecated import deprecated
4
5
 
5
6
  from PyViCare.PyViCareHeatingDevice import HeatingDevice, HeatingDeviceWithComponent
6
- from PyViCare.PyViCareUtils import handleAPICommandErrors, handleNotSupported
7
+ from PyViCare.PyViCareUtils import (PyViCareNotSupportedFeatureError,
8
+ handleAPICommandErrors, handleNotSupported)
7
9
  from PyViCare.PyViCareVentilationDevice import VentilationDevice
8
10
 
9
11
 
@@ -34,6 +36,13 @@ class HeatPump(HeatingDevice, VentilationDevice):
34
36
  def getEvaporator(self, evaporator) -> Evaporator:
35
37
  return Evaporator(self, evaporator)
36
38
 
39
+ @property
40
+ def inverters(self) -> List[Inverter]:
41
+ return [self.getInverter(x) for x in self.getAvailableCompressors()]
42
+
43
+ def getInverter(self, inverter) -> Inverter:
44
+ return Inverter(self, inverter)
45
+
37
46
  @handleNotSupported
38
47
  def getBufferMainTemperature(self):
39
48
  return self.getProperty("heating.bufferCylinder.sensors.temperature.main")["properties"]['value']['value']
@@ -313,6 +322,39 @@ class HeatPump(HeatingDevice, VentilationDevice):
313
322
  def getHeatingRodPowerConsumptionTotalThisYear(self) -> float:
314
323
  return float(self.getProperty("heating.heatingRod.power.consumption.total")["properties"]["year"]["value"][0])
315
324
 
325
+ # Cooling circuits
326
+ @property
327
+ def coolingCircuits(self) -> List[CoolingCircuit]:
328
+ return [self.getCoolingCircuit(x) for x in self.getAvailableCoolingCircuits()]
329
+
330
+ def getCoolingCircuit(self, circuit) -> CoolingCircuit:
331
+ return CoolingCircuit(self, circuit)
332
+
333
+ def getAvailableCoolingCircuits(self):
334
+ """Detect available cooling circuits (0, 1, 2, etc.)."""
335
+ available = []
336
+ for circuit in ['0', '1', '2', '3']:
337
+ with suppress(KeyError, PyViCareNotSupportedFeatureError):
338
+ if self.getProperty(f"heating.coolingCircuits.{circuit}.type") is not None:
339
+ available.append(circuit)
340
+ return available
341
+
342
+
343
+ class CoolingCircuit(HeatingDeviceWithComponent):
344
+ """Cooling circuit component for heat pumps with cooling capability."""
345
+
346
+ @property
347
+ def circuit(self) -> str:
348
+ return self.component
349
+
350
+ @handleNotSupported
351
+ def getType(self) -> str:
352
+ return str(self.getProperty(f"heating.coolingCircuits.{self.circuit}.type")["properties"]["value"]["value"])
353
+
354
+ @handleNotSupported
355
+ def getReverseActive(self) -> bool:
356
+ return bool(self.getProperty(f"heating.coolingCircuits.{self.circuit}.reverse")["properties"]["active"]["value"])
357
+
316
358
 
317
359
  class Compressor(HeatingDeviceWithComponent):
318
360
 
@@ -356,6 +398,10 @@ class Compressor(HeatingDeviceWithComponent):
356
398
  def getPhase(self):
357
399
  return self.getProperty(f"heating.compressors.{self.compressor}")["properties"]["phase"]["value"]
358
400
 
401
+ @handleNotSupported
402
+ def getSpeed(self) -> int:
403
+ return int(self.getProperty(f"heating.compressors.{self.compressor}.speed.current")["properties"]["value"]["value"])
404
+
359
405
  @handleNotSupported
360
406
  def getHeatProductionCurrent(self) -> float:
361
407
  return float(self.getProperty(f"heating.compressors.{self.compressor}.heat.production.current")["properties"]["value"]["value"])
@@ -480,6 +526,23 @@ class Compressor(HeatingDeviceWithComponent):
480
526
  # Shows the inlet temperature of the compressor.
481
527
  return float(self.getProperty(f"heating.compressors.{self.compressor}.sensors.temperature.inlet")["properties"]["value"]["value"])
482
528
 
529
+ @handleNotSupported
530
+ def getOilTemperature(self) -> float:
531
+ # Shows the oil temperature of the compressor.
532
+ return float(self.getProperty(f"heating.compressors.{self.compressor}.sensors.temperature.oil")["properties"]["value"]["value"])
533
+
534
+ def getMotorChamberTemperature(self) -> float:
535
+ # Shows the motor chamber temperature of the compressor.
536
+ return float(self.getProperty(f"heating.compressors.{self.compressor}.sensors.temperature.motorChamber")["properties"]["value"]["value"])
537
+
538
+ def getAmbientTemperature(self) -> float:
539
+ # Shows the ambient temperature of the compressor.
540
+ return float(self.getProperty(f"heating.compressors.{self.compressor}.sensors.temperature.ambient")["properties"]["value"]["value"])
541
+
542
+ def getOverheatTemperature(self) -> float:
543
+ # Shows the overheat temperature of the compressor.
544
+ return float(self.getProperty(f"heating.compressors.{self.compressor}.sensors.temperature.overheat")["properties"]["value"]["value"])
545
+
483
546
 
484
547
  class Evaporator(HeatingDeviceWithComponent):
485
548
 
@@ -581,3 +644,22 @@ class Condensor(HeatingDeviceWithComponent):
581
644
  def getLiquidTemperature(self) -> float:
582
645
  # Shows the liquid temperature of the condenser.
583
646
  return float(self.getProperty(f"heating.condensors.{self.condensor}.sensors.temperature.liquid")["properties"]["value"]["value"])
647
+
648
+
649
+ class Inverter(HeatingDeviceWithComponent):
650
+
651
+ @property
652
+ def inverter(self) -> str:
653
+ return self.component
654
+
655
+ @handleNotSupported
656
+ def getCurrent(self) -> float:
657
+ return float(self.getProperty(f"heating.inverters.{self.inverter}.sensors.power.current")["properties"]["value"]["value"])
658
+
659
+ @handleNotSupported
660
+ def getPower(self) -> float:
661
+ return float(self.getProperty(f"heating.inverters.{self.inverter}.sensors.power.output")["properties"]["value"]["value"])
662
+
663
+ @handleNotSupported
664
+ def getTemperature(self) -> float:
665
+ return float(self.getProperty(f"heating.inverters.{self.inverter}.sensors.temperature.powerModule")["properties"]["value"]["value"])
@@ -36,6 +36,10 @@ class HeatingDevice(Device):
36
36
  Note that currently, a new token is generated for each run.
37
37
  """
38
38
 
39
+ @handleNotSupported
40
+ def getWifiSignalStrength(self) -> int:
41
+ return int(self.getProperty("tcu.wifi")["properties"]["strength"]["value"])
42
+
39
43
  @property
40
44
  def circuits(self) -> List[Any]:
41
45
  return list([self.getCircuit(x) for x in self.getAvailableCircuits()])
@@ -194,6 +198,16 @@ class HeatingDevice(Device):
194
198
  return self.setProperty("heating.dhw.temperature.temp2", "setTargetTemperature",
195
199
  {"temperature": int(temperature)})
196
200
 
201
+ @handleNotSupported
202
+ def getDomesticHotWaterOperatingModes(self):
203
+ return self.getProperty("heating.dhw.operating.modes.active")[
204
+ "commands"]["setMode"]["params"]["mode"]["constraints"]["enum"]
205
+
206
+ @handleNotSupported
207
+ def getDomesticHotWaterActiveOperatingMode(self):
208
+ return self.getProperty("heating.dhw.operating.modes.active")[
209
+ "properties"]["value"]["value"]
210
+
197
211
  @handleAPICommandErrors
198
212
  def setDomesticHotWaterOperatingMode(self, mode):
199
213
  return self.setProperty("heating.dhw.operating.modes.active", "setMode",
@@ -105,6 +105,18 @@ class PyViCareInvalidDataError(Exception):
105
105
  pass
106
106
 
107
107
 
108
+ class PyViCareDeviceCommunicationError(Exception):
109
+ def __init__(self, response):
110
+ extended_payload = response.get("extendedPayload", {})
111
+ reason = extended_payload.get("reason", "Unknown")
112
+
113
+ msg = f'Device communication error. Reason: {reason}'
114
+
115
+ super().__init__(self, msg)
116
+ self.message = msg
117
+ self.reason = reason
118
+
119
+
108
120
  class PyViCareRateLimitError(Exception):
109
121
 
110
122
  def __init__(self, response):
@@ -12,6 +12,10 @@ class VentilationDevice(Device):
12
12
  Note that currently, a new token is generated for each run.
13
13
  """
14
14
 
15
+ @handleNotSupported
16
+ def getWifiSignalStrength(self) -> int:
17
+ return int(self.getProperty("tcu.wifi")["properties"]["strength"]["value"])
18
+
15
19
  @handleNotSupported
16
20
  def getVentilationDemand(self) -> str:
17
21
  return str(self.getProperty("ventilation.operating.state")["properties"]["demand"]["value"])
@@ -285,3 +289,19 @@ class VentilationDevice(Device):
285
289
  @handleNotSupported
286
290
  def getExhaustVolumeFlow(self) -> int:
287
291
  return int(self.getProperty("ventilation.volumeFlow.current.output")["properties"]["value"]["value"])
292
+
293
+ @handleNotSupported
294
+ def getConfiguredLevelOneVolumeFlow(self) -> int:
295
+ return int(self.getProperty("ventilation.levels.levelOne")["properties"]["volumeFlow"]["value"])
296
+
297
+ @handleNotSupported
298
+ def getConfiguredLevelTwoVolumeFlow(self) -> int:
299
+ return int(self.getProperty("ventilation.levels.levelTwo")["properties"]["volumeFlow"]["value"])
300
+
301
+ @handleNotSupported
302
+ def getConfiguredLevelThreeVolumeFlow(self) -> int:
303
+ return int(self.getProperty("ventilation.levels.levelThree")["properties"]["volumeFlow"]["value"])
304
+
305
+ @handleNotSupported
306
+ def getConfiguredLevelFourVolumeFlow(self) -> int:
307
+ return int(self.getProperty("ventilation.levels.levelFour")["properties"]["volumeFlow"]["value"])
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "PyViCare"
3
- version = "2.55.1"
3
+ version = "2.57.0"
4
4
  description = "Library to communicate with the Viessmann ViCare API."
5
5
  authors = [
6
6
  "Simon Gillet <mail+pyvicare@gillet.ninja>"
@@ -26,6 +26,7 @@ classifiers = [
26
26
  "Programming Language :: Python :: 3.10",
27
27
  "Programming Language :: Python :: 3.11",
28
28
  "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
29
30
  "Programming Language :: Python :: 3",
30
31
  "License :: OSI Approved :: Apache Software License",
31
32
  "Topic :: Software Development :: Libraries :: Python Modules",
@@ -51,7 +52,7 @@ mypy = "^1.11.2"
51
52
  pylint = "^4.0.0"
52
53
  pytest = "^9.0.0"
53
54
  pytest-cov = "^7.0.0"
54
- ruff = "^0.14.0"
55
+ ruff = "^0.15.0"
55
56
  types-deprecated = "^1.2.15.20241117"
56
57
  types-requests = ">=2.31"
57
58
 
File without changes
File without changes
File without changes