PyViCare 2.56.0__tar.gz → 2.58.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.
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PKG-INFO +1 -1
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCare.py +1 -1
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareAbstractOAuthManager.py +6 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareCachedService.py +13 -3
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareDeviceConfig.py +29 -4
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareFuelCell.py +20 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareGazBoiler.py +46 -1
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareHeatPump.py +296 -14
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareHeatingDevice.py +28 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareUtils.py +12 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareVentilationDevice.py +16 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/pyproject.toml +3 -2
- {pyvicare-2.56.0 → pyvicare-2.58.0}/LICENSE +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/Feature.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareBrowserOAuthManager.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareDevice.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareElectricalEnergySystem.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareFloorHeating.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareGateway.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareHeatCurveCalculation.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareHybrid.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareOAuthManager.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareOilBoiler.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCarePelletsBoiler.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareRadiatorActuator.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareRepeater.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareRoomSensor.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/PyViCareService.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/PyViCare/__init__.py +0 -0
- {pyvicare-2.56.0 → pyvicare-2.58.0}/README.md +0 -0
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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)
|
|
@@ -23,6 +23,7 @@ class FuelCell(HeatingDevice):
|
|
|
23
23
|
def getReturnTemperature(self):
|
|
24
24
|
return self.getProperty("heating.sensors.temperature.return")["properties"]["value"]["value"]
|
|
25
25
|
|
|
26
|
+
# Total power consumption:
|
|
26
27
|
@handleNotSupported
|
|
27
28
|
def getPowerConsumptionUnit(self):
|
|
28
29
|
return self.getProperty("heating.power.consumption.total")["properties"]["day"]["unit"]
|
|
@@ -59,6 +60,7 @@ class FuelCell(HeatingDevice):
|
|
|
59
60
|
def getPowerConsumptionThisYear(self):
|
|
60
61
|
return self.getProperty('heating.power.consumption.total')['properties']['year']['value'][0]
|
|
61
62
|
|
|
63
|
+
# Power consumption for Heating:
|
|
62
64
|
@handleNotSupported
|
|
63
65
|
def getPowerConsumptionHeatingUnit(self):
|
|
64
66
|
return self.getProperty("heating.power.consumption.heating")["properties"]["day"]["unit"]
|
|
@@ -95,6 +97,24 @@ class FuelCell(HeatingDevice):
|
|
|
95
97
|
def getPowerConsumptionHeatingThisYear(self):
|
|
96
98
|
return self.getProperty('heating.power.consumption.heating')['properties']['year']['value'][0]
|
|
97
99
|
|
|
100
|
+
# Power consumption for Domestic Hot Water:
|
|
101
|
+
@handleNotSupported
|
|
102
|
+
def getPowerConsumptionDomesticHotWaterUnit(self):
|
|
103
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["day"]["unit"]
|
|
104
|
+
|
|
105
|
+
@handleNotSupported
|
|
106
|
+
def getPowerConsumptionDomesticHotWaterToday(self):
|
|
107
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["day"]["value"][0]
|
|
108
|
+
|
|
109
|
+
@handleNotSupported
|
|
110
|
+
def getPowerConsumptionDomesticHotWaterThisMonth(self):
|
|
111
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["month"]["value"][0]
|
|
112
|
+
|
|
113
|
+
@handleNotSupported
|
|
114
|
+
def getPowerConsumptionDomesticHotWaterThisYear(self):
|
|
115
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["year"]["value"][0]
|
|
116
|
+
|
|
117
|
+
# Gas consumption:
|
|
98
118
|
@handleNotSupported
|
|
99
119
|
def getGasConsumptionUnit(self):
|
|
100
120
|
return self.getProperty("heating.gas.consumption.total")["properties"]["day"]["unit"]
|
|
@@ -103,9 +103,13 @@ class GazBoiler(HeatingDevice):
|
|
|
103
103
|
def getDomesticHotWaterChargingLevel(self):
|
|
104
104
|
return self.getProperty("heating.dhw.charging.level")["properties"]["value"]["value"]
|
|
105
105
|
|
|
106
|
+
# Total power consumption:
|
|
106
107
|
@handleNotSupported
|
|
107
108
|
def getPowerConsumptionUnit(self):
|
|
108
|
-
|
|
109
|
+
try :
|
|
110
|
+
return self.getProperty("heating.power.consumption.total")["properties"]["day"]["unit"]
|
|
111
|
+
except KeyError:
|
|
112
|
+
return self.getProperty("heating.power.consumption.total")["properties"]["unit"]["value"]
|
|
109
113
|
|
|
110
114
|
@handleNotSupported
|
|
111
115
|
def getPowerConsumptionDays(self):
|
|
@@ -139,6 +143,7 @@ class GazBoiler(HeatingDevice):
|
|
|
139
143
|
def getPowerConsumptionThisYear(self):
|
|
140
144
|
return self.getProperty("heating.power.consumption.total")["properties"]["year"]["value"][0]
|
|
141
145
|
|
|
146
|
+
# Flow
|
|
142
147
|
@handleNotSupported
|
|
143
148
|
def getVolumetricFlowReturn(self):
|
|
144
149
|
return self.getProperty("heating.sensors.volumetricFlow.allengra")["properties"]["value"]["value"]
|
|
@@ -204,6 +209,26 @@ class GazBoiler(HeatingDevice):
|
|
|
204
209
|
|
|
205
210
|
# Power consumption for Heating:
|
|
206
211
|
@handleNotSupported
|
|
212
|
+
def getPowerConsumptionHeatingUnit(self):
|
|
213
|
+
try:
|
|
214
|
+
return self.getProperty("heating.power.consumption.heating")["properties"]["day"]["unit"]
|
|
215
|
+
except KeyError:
|
|
216
|
+
return self.getProperty("heating.power.consumption.heating")["properties"]["unit"]["value"]
|
|
217
|
+
|
|
218
|
+
@handleNotSupported
|
|
219
|
+
def getPowerConsumptionHeatingToday(self):
|
|
220
|
+
return self.getProperty("heating.power.consumption.heating")["properties"]["day"]["value"][0]
|
|
221
|
+
|
|
222
|
+
@handleNotSupported
|
|
223
|
+
def getPowerConsumptionHeatingThisMonth(self):
|
|
224
|
+
return self.getProperty("heating.power.consumption.heating")["properties"]["month"]["value"][0]
|
|
225
|
+
|
|
226
|
+
@handleNotSupported
|
|
227
|
+
def getPowerConsumptionHeatingThisYear(self):
|
|
228
|
+
return self.getProperty("heating.power.consumption.heating")["properties"]["year"]["value"][0]
|
|
229
|
+
|
|
230
|
+
# Power summary consumption for Heating:
|
|
231
|
+
@handleNotSupported
|
|
207
232
|
def getPowerSummaryConsumptionHeatingUnit(self):
|
|
208
233
|
return self.getProperty("heating.power.consumption.summary.heating")["properties"]["currentDay"]["unit"]
|
|
209
234
|
|
|
@@ -233,6 +258,26 @@ class GazBoiler(HeatingDevice):
|
|
|
233
258
|
|
|
234
259
|
# Power consumption for Domestic Hot Water:
|
|
235
260
|
@handleNotSupported
|
|
261
|
+
def getPowerConsumptionDomesticHotWaterUnit(self):
|
|
262
|
+
try:
|
|
263
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["day"]["unit"]
|
|
264
|
+
except KeyError:
|
|
265
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["unit"]["value"]
|
|
266
|
+
|
|
267
|
+
@handleNotSupported
|
|
268
|
+
def getPowerConsumptionDomesticHotWaterToday(self):
|
|
269
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["day"]["value"][0]
|
|
270
|
+
|
|
271
|
+
@handleNotSupported
|
|
272
|
+
def getPowerConsumptionDomesticHotWaterThisMonth(self):
|
|
273
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["month"]["value"][0]
|
|
274
|
+
|
|
275
|
+
@handleNotSupported
|
|
276
|
+
def getPowerConsumptionDomesticHotWaterThisYear(self):
|
|
277
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["year"]["value"][0]
|
|
278
|
+
|
|
279
|
+
# Power summary consumption for Domestic Hot Water:
|
|
280
|
+
@handleNotSupported
|
|
236
281
|
def getPowerSummaryConsumptionDomesticHotWaterUnit(self):
|
|
237
282
|
return self.getProperty("heating.power.consumption.summary.dhw")["properties"]["currentDay"]["unit"]
|
|
238
283
|
|
|
@@ -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
|
|
7
|
+
from PyViCare.PyViCareUtils import (PyViCareNotSupportedFeatureError,
|
|
8
|
+
handleAPICommandErrors, handleNotSupported)
|
|
7
9
|
from PyViCare.PyViCareVentilationDevice import VentilationDevice
|
|
8
10
|
|
|
9
11
|
|
|
@@ -43,14 +45,31 @@ class HeatPump(HeatingDevice, VentilationDevice):
|
|
|
43
45
|
|
|
44
46
|
@handleNotSupported
|
|
45
47
|
def getBufferMainTemperature(self):
|
|
46
|
-
return self.getProperty("heating.bufferCylinder.sensors.temperature.main")["properties"][
|
|
48
|
+
return self.getProperty("heating.bufferCylinder.sensors.temperature.main")["properties"]["value"]["value"]
|
|
47
49
|
|
|
48
50
|
@handleNotSupported
|
|
49
51
|
def getBufferTopTemperature(self):
|
|
50
|
-
return self.getProperty("heating.bufferCylinder.sensors.temperature.top")["properties"][
|
|
52
|
+
return self.getProperty("heating.bufferCylinder.sensors.temperature.top")["properties"]["value"]["value"]
|
|
51
53
|
|
|
52
54
|
# Power consumption for Heating:
|
|
53
55
|
@handleNotSupported
|
|
56
|
+
def getPowerConsumptionHeatingUnit(self):
|
|
57
|
+
return self.getProperty("heating.power.consumption.heating")["properties"]["day"]["unit"]
|
|
58
|
+
|
|
59
|
+
@handleNotSupported
|
|
60
|
+
def getPowerConsumptionHeatingToday(self):
|
|
61
|
+
return self.getProperty("heating.power.consumption.heating")["properties"]["day"]["value"][0]
|
|
62
|
+
|
|
63
|
+
@handleNotSupported
|
|
64
|
+
def getPowerConsumptionHeatingThisMonth(self):
|
|
65
|
+
return self.getProperty("heating.power.consumption.heating")["properties"]["month"]["value"][0]
|
|
66
|
+
|
|
67
|
+
@handleNotSupported
|
|
68
|
+
def getPowerConsumptionHeatingThisYear(self):
|
|
69
|
+
return self.getProperty("heating.power.consumption.heating")["properties"]["year"]["value"][0]
|
|
70
|
+
|
|
71
|
+
# Power summary consumption for Heating:
|
|
72
|
+
@handleNotSupported
|
|
54
73
|
def getPowerSummaryConsumptionHeatingUnit(self):
|
|
55
74
|
return self.getProperty("heating.power.consumption.summary.heating")["properties"]["currentDay"]["unit"]
|
|
56
75
|
|
|
@@ -95,6 +114,7 @@ class HeatPump(HeatingDevice, VentilationDevice):
|
|
|
95
114
|
def getPowerConsumptionCoolingThisYear(self):
|
|
96
115
|
return self.getProperty("heating.power.consumption.cooling")["properties"]["year"]["value"][0]
|
|
97
116
|
|
|
117
|
+
# Total power consumption:
|
|
98
118
|
@handleNotSupported
|
|
99
119
|
def getPowerConsumptionUnit(self):
|
|
100
120
|
return self.getProperty("heating.power.consumption.total")["properties"]["day"]["unit"]
|
|
@@ -103,11 +123,32 @@ class HeatPump(HeatingDevice, VentilationDevice):
|
|
|
103
123
|
def getPowerConsumptionToday(self):
|
|
104
124
|
return self.getProperty("heating.power.consumption.total")["properties"]["day"]["value"][0]
|
|
105
125
|
|
|
126
|
+
@handleNotSupported
|
|
127
|
+
def getPowerConsumptionThisMonth(self):
|
|
128
|
+
return self.getProperty("heating.power.consumption.total")["properties"]["month"]["value"][0]
|
|
129
|
+
|
|
130
|
+
@handleNotSupported
|
|
131
|
+
def getPowerConsumptionThisYear(self):
|
|
132
|
+
return self.getProperty("heating.power.consumption.total")["properties"]["year"]["value"][0]
|
|
133
|
+
|
|
134
|
+
# Power consumption for Domestic Hot Water:
|
|
135
|
+
@handleNotSupported
|
|
136
|
+
def getPowerConsumptionDomesticHotWaterUnit(self):
|
|
137
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["day"]["unit"]
|
|
138
|
+
|
|
106
139
|
@handleNotSupported
|
|
107
140
|
def getPowerConsumptionDomesticHotWaterToday(self):
|
|
108
141
|
return self.getProperty("heating.power.consumption.dhw")["properties"]["day"]["value"][0]
|
|
109
142
|
|
|
110
|
-
|
|
143
|
+
@handleNotSupported
|
|
144
|
+
def getPowerConsumptionDomesticHotWaterThisMonth(self):
|
|
145
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["month"]["value"][0]
|
|
146
|
+
|
|
147
|
+
@handleNotSupported
|
|
148
|
+
def getPowerConsumptionDomesticHotWaterThisYear(self):
|
|
149
|
+
return self.getProperty("heating.power.consumption.dhw")["properties"]["year"]["value"][0]
|
|
150
|
+
|
|
151
|
+
# Power summary consumption for Domestic Hot Water:
|
|
111
152
|
@handleNotSupported
|
|
112
153
|
def getPowerSummaryConsumptionDomesticHotWaterUnit(self):
|
|
113
154
|
return self.getProperty("heating.power.consumption.summary.dhw")["properties"]["currentDay"]["unit"]
|
|
@@ -284,6 +325,24 @@ class HeatPump(HeatingDevice, VentilationDevice):
|
|
|
284
325
|
def getSeasonalPerformanceFactorTotal(self) -> float:
|
|
285
326
|
return float(self.getProperty("heating.spf.total")["properties"]["value"]["value"])
|
|
286
327
|
|
|
328
|
+
# COP (Coefficient of Performance) - instantaneous efficiency metrics
|
|
329
|
+
# Some devices expose COP instead of SPF
|
|
330
|
+
@handleNotSupported
|
|
331
|
+
def getCoefficientOfPerformanceHeating(self) -> float:
|
|
332
|
+
return float(self.getProperty("heating.cop.heating")["properties"]["value"]["value"])
|
|
333
|
+
|
|
334
|
+
@handleNotSupported
|
|
335
|
+
def getCoefficientOfPerformanceDHW(self) -> float:
|
|
336
|
+
return float(self.getProperty("heating.cop.dhw")["properties"]["value"]["value"])
|
|
337
|
+
|
|
338
|
+
@handleNotSupported
|
|
339
|
+
def getCoefficientOfPerformanceTotal(self) -> float:
|
|
340
|
+
return float(self.getProperty("heating.cop.total")["properties"]["value"]["value"])
|
|
341
|
+
|
|
342
|
+
@handleNotSupported
|
|
343
|
+
def getCoefficientOfPerformanceCooling(self) -> float:
|
|
344
|
+
return float(self.getProperty("heating.cop.cooling")["properties"]["value"]["value"])
|
|
345
|
+
|
|
287
346
|
@handleNotSupported
|
|
288
347
|
def getHeatingRodStarts(self) -> int:
|
|
289
348
|
return int(self.getProperty("heating.heatingRod.statistics")["properties"]["starts"]["value"])
|
|
@@ -320,6 +379,191 @@ class HeatPump(HeatingDevice, VentilationDevice):
|
|
|
320
379
|
def getHeatingRodPowerConsumptionTotalThisYear(self) -> float:
|
|
321
380
|
return float(self.getProperty("heating.heatingRod.power.consumption.total")["properties"]["year"]["value"][0])
|
|
322
381
|
|
|
382
|
+
# Heating rod power consumption summary for DHW:
|
|
383
|
+
@handleNotSupported
|
|
384
|
+
def getHeatingRodPowerConsumptionSummaryDHWUnit(self) -> str:
|
|
385
|
+
return str(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["currentDay"]["unit"])
|
|
386
|
+
|
|
387
|
+
@handleNotSupported
|
|
388
|
+
def getHeatingRodPowerConsumptionSummaryDHWCurrentDay(self) -> float:
|
|
389
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["currentDay"]["value"])
|
|
390
|
+
|
|
391
|
+
@handleNotSupported
|
|
392
|
+
def getHeatingRodPowerConsumptionSummaryDHWCurrentMonth(self) -> float:
|
|
393
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["currentMonth"]["value"])
|
|
394
|
+
|
|
395
|
+
@handleNotSupported
|
|
396
|
+
def getHeatingRodPowerConsumptionSummaryDHWCurrentYear(self) -> float:
|
|
397
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["currentYear"]["value"])
|
|
398
|
+
|
|
399
|
+
@handleNotSupported
|
|
400
|
+
def getHeatingRodPowerConsumptionSummaryDHWLastMonth(self) -> float:
|
|
401
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["lastMonth"]["value"])
|
|
402
|
+
|
|
403
|
+
@handleNotSupported
|
|
404
|
+
def getHeatingRodPowerConsumptionSummaryDHWLastSevenDays(self) -> float:
|
|
405
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["lastSevenDays"]["value"])
|
|
406
|
+
|
|
407
|
+
@handleNotSupported
|
|
408
|
+
def getHeatingRodPowerConsumptionSummaryDHWLastYear(self) -> float:
|
|
409
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.dhw")["properties"]["lastYear"]["value"])
|
|
410
|
+
|
|
411
|
+
# Heating rod power consumption summary for Heating:
|
|
412
|
+
@handleNotSupported
|
|
413
|
+
def getHeatingRodPowerConsumptionSummaryHeatingUnit(self) -> str:
|
|
414
|
+
return str(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["currentDay"]["unit"])
|
|
415
|
+
|
|
416
|
+
@handleNotSupported
|
|
417
|
+
def getHeatingRodPowerConsumptionSummaryHeatingCurrentDay(self) -> float:
|
|
418
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["currentDay"]["value"])
|
|
419
|
+
|
|
420
|
+
@handleNotSupported
|
|
421
|
+
def getHeatingRodPowerConsumptionSummaryHeatingCurrentMonth(self) -> float:
|
|
422
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["currentMonth"]["value"])
|
|
423
|
+
|
|
424
|
+
@handleNotSupported
|
|
425
|
+
def getHeatingRodPowerConsumptionSummaryHeatingCurrentYear(self) -> float:
|
|
426
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["currentYear"]["value"])
|
|
427
|
+
|
|
428
|
+
@handleNotSupported
|
|
429
|
+
def getHeatingRodPowerConsumptionSummaryHeatingLastMonth(self) -> float:
|
|
430
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["lastMonth"]["value"])
|
|
431
|
+
|
|
432
|
+
@handleNotSupported
|
|
433
|
+
def getHeatingRodPowerConsumptionSummaryHeatingLastSevenDays(self) -> float:
|
|
434
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["lastSevenDays"]["value"])
|
|
435
|
+
|
|
436
|
+
@handleNotSupported
|
|
437
|
+
def getHeatingRodPowerConsumptionSummaryHeatingLastYear(self) -> float:
|
|
438
|
+
return float(self.getProperty("heating.heatingRod.power.consumption.summary.heating")["properties"]["lastYear"]["value"])
|
|
439
|
+
|
|
440
|
+
# Heating rod runtime by level
|
|
441
|
+
@handleNotSupported
|
|
442
|
+
def getHeatingRodRuntimeLevelOne(self) -> int:
|
|
443
|
+
return int(self.getProperty("heating.heatingRod.runtime")["properties"]["levelOne"]["value"])
|
|
444
|
+
|
|
445
|
+
@handleNotSupported
|
|
446
|
+
def getHeatingRodRuntimeLevelTwo(self) -> int:
|
|
447
|
+
return int(self.getProperty("heating.heatingRod.runtime")["properties"]["levelTwo"]["value"])
|
|
448
|
+
|
|
449
|
+
@handleNotSupported
|
|
450
|
+
def getHeatingRodRuntimeLevelOneUnit(self) -> str:
|
|
451
|
+
return str(self.getProperty("heating.heatingRod.runtime")["properties"]["levelOne"]["unit"])
|
|
452
|
+
|
|
453
|
+
# Additional pressure sensors (refrigerant circuit)
|
|
454
|
+
@handleNotSupported
|
|
455
|
+
def getHotGasPressure(self) -> float:
|
|
456
|
+
return float(self.getProperty("heating.sensors.pressure.hotGas")["properties"]["value"]["value"])
|
|
457
|
+
|
|
458
|
+
@handleNotSupported
|
|
459
|
+
def getHotGasPressureUnit(self) -> str:
|
|
460
|
+
return str(self.getProperty("heating.sensors.pressure.hotGas")["properties"]["value"]["unit"])
|
|
461
|
+
|
|
462
|
+
@handleNotSupported
|
|
463
|
+
def getSuctionGasPressure(self) -> float:
|
|
464
|
+
return float(self.getProperty("heating.sensors.pressure.suctionGas")["properties"]["value"]["value"])
|
|
465
|
+
|
|
466
|
+
@handleNotSupported
|
|
467
|
+
def getSuctionGasPressureUnit(self) -> str:
|
|
468
|
+
return str(self.getProperty("heating.sensors.pressure.suctionGas")["properties"]["value"]["unit"])
|
|
469
|
+
|
|
470
|
+
# Additional temperature sensors (refrigerant circuit)
|
|
471
|
+
@handleNotSupported
|
|
472
|
+
def getHotGasTemperature(self) -> float:
|
|
473
|
+
return float(self.getProperty("heating.sensors.temperature.hotGas")["properties"]["value"]["value"])
|
|
474
|
+
|
|
475
|
+
@handleNotSupported
|
|
476
|
+
def getHotGasTemperatureUnit(self) -> str:
|
|
477
|
+
return str(self.getProperty("heating.sensors.temperature.hotGas")["properties"]["value"]["unit"])
|
|
478
|
+
|
|
479
|
+
@handleNotSupported
|
|
480
|
+
def getLiquidGasTemperature(self) -> float:
|
|
481
|
+
return float(self.getProperty("heating.sensors.temperature.liquidGas")["properties"]["value"]["value"])
|
|
482
|
+
|
|
483
|
+
@handleNotSupported
|
|
484
|
+
def getLiquidGasTemperatureUnit(self) -> str:
|
|
485
|
+
return str(self.getProperty("heating.sensors.temperature.liquidGas")["properties"]["value"]["unit"])
|
|
486
|
+
|
|
487
|
+
@handleNotSupported
|
|
488
|
+
def getSuctionGasTemperature(self) -> float:
|
|
489
|
+
return float(self.getProperty("heating.sensors.temperature.suctionGas")["properties"]["value"]["value"])
|
|
490
|
+
|
|
491
|
+
@handleNotSupported
|
|
492
|
+
def getSuctionGasTemperatureUnit(self) -> str:
|
|
493
|
+
return str(self.getProperty("heating.sensors.temperature.suctionGas")["properties"]["value"]["unit"])
|
|
494
|
+
|
|
495
|
+
# Main ECU runtime
|
|
496
|
+
@handleNotSupported
|
|
497
|
+
def getMainECURuntime(self) -> int:
|
|
498
|
+
return int(self.getProperty("heating.device.mainECU")["properties"]["runtime"]["value"])
|
|
499
|
+
|
|
500
|
+
@handleNotSupported
|
|
501
|
+
def getMainECURuntimeUnit(self) -> str:
|
|
502
|
+
return str(self.getProperty("heating.device.mainECU")["properties"]["runtime"]["unit"])
|
|
503
|
+
|
|
504
|
+
# Configuration values
|
|
505
|
+
@handleNotSupported
|
|
506
|
+
def getConfigurationBufferTemperatureMax(self) -> float:
|
|
507
|
+
return float(self.getProperty("heating.configuration.buffer.temperature.max")["properties"]["value"]["value"])
|
|
508
|
+
|
|
509
|
+
@handleNotSupported
|
|
510
|
+
def getConfigurationBufferTemperatureMaxUnit(self) -> str:
|
|
511
|
+
return str(self.getProperty("heating.configuration.buffer.temperature.max")["properties"]["value"]["unit"])
|
|
512
|
+
|
|
513
|
+
@handleNotSupported
|
|
514
|
+
def getConfigurationOutsideTemperatureDampingFactor(self) -> int:
|
|
515
|
+
return int(self.getProperty("heating.configuration.temperature.outside.DampingFactor")["properties"]["value"]["value"])
|
|
516
|
+
|
|
517
|
+
@handleNotSupported
|
|
518
|
+
def getConfigurationOutsideTemperatureDampingFactorUnit(self) -> str:
|
|
519
|
+
return str(self.getProperty("heating.configuration.temperature.outside.DampingFactor")["properties"]["value"]["unit"])
|
|
520
|
+
|
|
521
|
+
@handleNotSupported
|
|
522
|
+
def getConfigurationHeatingRodDHWApproved(self) -> bool:
|
|
523
|
+
return bool(self.getProperty("heating.configuration.heatingRod.dhw")["properties"]["useApproved"]["value"])
|
|
524
|
+
|
|
525
|
+
@handleNotSupported
|
|
526
|
+
def getConfigurationHeatingRodHeatingApproved(self) -> bool:
|
|
527
|
+
return bool(self.getProperty("heating.configuration.heatingRod.heating")["properties"]["useApproved"]["value"])
|
|
528
|
+
|
|
529
|
+
@handleNotSupported
|
|
530
|
+
def getConfigurationDHWHeaterApproved(self) -> bool:
|
|
531
|
+
return bool(self.getProperty("heating.configuration.dhwHeater")["properties"]["useApproved"]["value"])
|
|
532
|
+
|
|
533
|
+
# Cooling circuits
|
|
534
|
+
@property
|
|
535
|
+
def coolingCircuits(self) -> List[CoolingCircuit]:
|
|
536
|
+
return [self.getCoolingCircuit(x) for x in self.getAvailableCoolingCircuits()]
|
|
537
|
+
|
|
538
|
+
def getCoolingCircuit(self, circuit) -> CoolingCircuit:
|
|
539
|
+
return CoolingCircuit(self, circuit)
|
|
540
|
+
|
|
541
|
+
def getAvailableCoolingCircuits(self):
|
|
542
|
+
"""Detect available cooling circuits (0, 1, 2, etc.)."""
|
|
543
|
+
available = []
|
|
544
|
+
for circuit in ['0', '1', '2', '3']:
|
|
545
|
+
with suppress(KeyError, PyViCareNotSupportedFeatureError):
|
|
546
|
+
if self.getProperty(f"heating.coolingCircuits.{circuit}.type") is not None:
|
|
547
|
+
available.append(circuit)
|
|
548
|
+
return available
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
class CoolingCircuit(HeatingDeviceWithComponent):
|
|
552
|
+
"""Cooling circuit component for heat pumps with cooling capability."""
|
|
553
|
+
|
|
554
|
+
@property
|
|
555
|
+
def circuit(self) -> str:
|
|
556
|
+
return self.component
|
|
557
|
+
|
|
558
|
+
@handleNotSupported
|
|
559
|
+
def getType(self) -> str:
|
|
560
|
+
return str(self.getProperty(f"heating.coolingCircuits.{self.circuit}.type")["properties"]["value"]["value"])
|
|
561
|
+
|
|
562
|
+
@handleNotSupported
|
|
563
|
+
def getReverseActive(self) -> bool:
|
|
564
|
+
return bool(self.getProperty(f"heating.coolingCircuits.{self.circuit}.reverse")["properties"]["active"]["value"])
|
|
565
|
+
|
|
566
|
+
|
|
323
567
|
|
|
324
568
|
class Compressor(HeatingDeviceWithComponent):
|
|
325
569
|
|
|
@@ -335,25 +579,45 @@ class Compressor(HeatingDeviceWithComponent):
|
|
|
335
579
|
def getHours(self):
|
|
336
580
|
return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hours"]["value"]
|
|
337
581
|
|
|
338
|
-
@handleNotSupported
|
|
339
582
|
def getHoursLoadClass1(self):
|
|
340
|
-
|
|
583
|
+
"""Get hours in load class 1. Tries 'statistics' path first, then 'statistics.load'."""
|
|
584
|
+
with suppress(KeyError):
|
|
585
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassOne"]["value"]
|
|
586
|
+
with suppress(KeyError):
|
|
587
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassOne"]["value"]
|
|
588
|
+
raise PyViCareNotSupportedFeatureError("getHoursLoadClass1")
|
|
341
589
|
|
|
342
|
-
@handleNotSupported
|
|
343
590
|
def getHoursLoadClass2(self):
|
|
344
|
-
|
|
591
|
+
"""Get hours in load class 2. Tries 'statistics' path first, then 'statistics.load'."""
|
|
592
|
+
with suppress(KeyError):
|
|
593
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassTwo"]["value"]
|
|
594
|
+
with suppress(KeyError):
|
|
595
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassTwo"]["value"]
|
|
596
|
+
raise PyViCareNotSupportedFeatureError("getHoursLoadClass2")
|
|
345
597
|
|
|
346
|
-
@handleNotSupported
|
|
347
598
|
def getHoursLoadClass3(self):
|
|
348
|
-
|
|
599
|
+
"""Get hours in load class 3. Tries 'statistics' path first, then 'statistics.load'."""
|
|
600
|
+
with suppress(KeyError):
|
|
601
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassThree"]["value"]
|
|
602
|
+
with suppress(KeyError):
|
|
603
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassThree"]["value"]
|
|
604
|
+
raise PyViCareNotSupportedFeatureError("getHoursLoadClass3")
|
|
349
605
|
|
|
350
|
-
@handleNotSupported
|
|
351
606
|
def getHoursLoadClass4(self):
|
|
352
|
-
|
|
607
|
+
"""Get hours in load class 4. Tries 'statistics' path first, then 'statistics.load'."""
|
|
608
|
+
with suppress(KeyError):
|
|
609
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassFour"]["value"]
|
|
610
|
+
with suppress(KeyError):
|
|
611
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassFour"]["value"]
|
|
612
|
+
raise PyViCareNotSupportedFeatureError("getHoursLoadClass4")
|
|
353
613
|
|
|
354
|
-
@handleNotSupported
|
|
355
614
|
def getHoursLoadClass5(self):
|
|
356
|
-
|
|
615
|
+
"""Get hours in load class 5. Tries 'statistics' path first, then 'statistics.load'."""
|
|
616
|
+
with suppress(KeyError):
|
|
617
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics")["properties"]["hoursLoadClassFive"]["value"]
|
|
618
|
+
with suppress(KeyError):
|
|
619
|
+
return self.getProperty(f"heating.compressors.{self.compressor}.statistics.load")["properties"]["hoursLoadClassFive"]["value"]
|
|
620
|
+
raise PyViCareNotSupportedFeatureError("getHoursLoadClass5")
|
|
357
621
|
|
|
358
622
|
@handleNotSupported
|
|
359
623
|
def getActive(self):
|
|
@@ -363,6 +627,24 @@ class Compressor(HeatingDeviceWithComponent):
|
|
|
363
627
|
def getPhase(self):
|
|
364
628
|
return self.getProperty(f"heating.compressors.{self.compressor}")["properties"]["phase"]["value"]
|
|
365
629
|
|
|
630
|
+
@handleNotSupported
|
|
631
|
+
def getPower(self) -> float:
|
|
632
|
+
# Returns the nominal/maximum power of the compressor in kW
|
|
633
|
+
return float(self.getProperty(f"heating.compressors.{self.compressor}.power")["properties"]["value"]["value"])
|
|
634
|
+
|
|
635
|
+
@handleNotSupported
|
|
636
|
+
def getPowerUnit(self) -> str:
|
|
637
|
+
return str(self.getProperty(f"heating.compressors.{self.compressor}.power")["properties"]["value"]["unit"])
|
|
638
|
+
|
|
639
|
+
@handleNotSupported
|
|
640
|
+
def getModulation(self) -> int:
|
|
641
|
+
# Returns the current compressor modulation/power level as percentage (0-100)
|
|
642
|
+
return int(self.getProperty(f"heating.compressors.{self.compressor}.sensors.power")["properties"]["value"]["value"])
|
|
643
|
+
|
|
644
|
+
@handleNotSupported
|
|
645
|
+
def getModulationUnit(self) -> str:
|
|
646
|
+
return str(self.getProperty(f"heating.compressors.{self.compressor}.sensors.power")["properties"]["value"]["unit"])
|
|
647
|
+
|
|
366
648
|
@handleNotSupported
|
|
367
649
|
def getSpeed(self) -> int:
|
|
368
650
|
return int(self.getProperty(f"heating.compressors.{self.compressor}.speed.current")["properties"]["value"]["value"])
|
|
@@ -198,6 +198,16 @@ class HeatingDevice(Device):
|
|
|
198
198
|
return self.setProperty("heating.dhw.temperature.temp2", "setTargetTemperature",
|
|
199
199
|
{"temperature": int(temperature)})
|
|
200
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
|
+
|
|
201
211
|
@handleAPICommandErrors
|
|
202
212
|
def setDomesticHotWaterOperatingMode(self, mode):
|
|
203
213
|
return self.setProperty("heating.dhw.operating.modes.active", "setMode",
|
|
@@ -358,6 +368,15 @@ class HeatingDevice(Device):
|
|
|
358
368
|
return self.getProperty("heating.primaryCircuit.sensors.temperature.return")["properties"]["value"][
|
|
359
369
|
"value"]
|
|
360
370
|
|
|
371
|
+
@handleNotSupported
|
|
372
|
+
def getPrimaryCircuitPumpRotation(self) -> float:
|
|
373
|
+
"""Get primary circuit pump rotation/speed as percentage."""
|
|
374
|
+
return float(self.getProperty("heating.primaryCircuit.sensors.rotation")["properties"]["value"]["value"])
|
|
375
|
+
|
|
376
|
+
@handleNotSupported
|
|
377
|
+
def getPrimaryCircuitPumpRotationUnit(self):
|
|
378
|
+
return self.getProperty("heating.primaryCircuit.sensors.rotation")["properties"]["value"]["unit"]
|
|
379
|
+
|
|
361
380
|
@handleNotSupported
|
|
362
381
|
def getSupplyTemperatureSecondaryCircuit(self):
|
|
363
382
|
return self.getProperty("heating.secondaryCircuit.sensors.temperature.supply")["properties"]["value"][
|
|
@@ -538,6 +557,15 @@ class HeatingCircuit(HeatingDeviceWithComponent):
|
|
|
538
557
|
self.getProperty(f"heating.circuits.{self.circuit}.sensors.temperature.supply")["properties"][
|
|
539
558
|
"value"]["value"]
|
|
540
559
|
|
|
560
|
+
@handleNotSupported
|
|
561
|
+
def getTargetTemperature(self) -> float:
|
|
562
|
+
"""Get the circuit target temperature."""
|
|
563
|
+
return float(self.getProperty(f"heating.circuits.{self.circuit}.temperature")["properties"]["value"]["value"])
|
|
564
|
+
|
|
565
|
+
@handleNotSupported
|
|
566
|
+
def getTargetTemperatureUnit(self):
|
|
567
|
+
return self.getProperty(f"heating.circuits.{self.circuit}.temperature")["properties"]["value"]["unit"]
|
|
568
|
+
|
|
541
569
|
@handleNotSupported
|
|
542
570
|
def getRoomTemperature(self):
|
|
543
571
|
return self.getProperty(f"heating.circuits.{self.circuit}.sensors.temperature.room")["properties"][
|
|
@@ -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):
|
|
@@ -289,3 +289,19 @@ class VentilationDevice(Device):
|
|
|
289
289
|
@handleNotSupported
|
|
290
290
|
def getExhaustVolumeFlow(self) -> int:
|
|
291
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.
|
|
3
|
+
version = "2.58.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.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|