PyViCare 2.33.0__tar.gz → 2.34.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.33.0 → pyvicare-2.34.0}/PKG-INFO +28 -10
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/Feature.py +1 -1
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareAbstractOAuthManager.py +3 -2
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareDeviceConfig.py +2 -1
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareHeatPump.py +20 -4
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareHeatingDevice.py +4 -4
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareService.py +1 -7
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareVentilationDevice.py +1 -2
- {pyvicare-2.33.0 → pyvicare-2.34.0}/README.md +4 -4
- pyvicare-2.34.0/pyproject.toml +116 -0
- pyvicare-2.33.0/PyViCare.egg-info/PKG-INFO +0 -186
- pyvicare-2.33.0/PyViCare.egg-info/SOURCES.txt +0 -62
- pyvicare-2.33.0/PyViCare.egg-info/dependency_links.txt +0 -1
- pyvicare-2.33.0/PyViCare.egg-info/requires.txt +0 -1
- pyvicare-2.33.0/PyViCare.egg-info/top_level.txt +0 -1
- pyvicare-2.33.0/setup.cfg +0 -4
- pyvicare-2.33.0/setup.py +0 -23
- pyvicare-2.33.0/tests/test_E3_TCU300_ethernet.py +0 -19
- pyvicare-2.33.0/tests/test_GenericDevice.py +0 -54
- pyvicare-2.33.0/tests/test_Integration.py +0 -121
- pyvicare-2.33.0/tests/test_PyViCareCachedService.py +0 -69
- pyvicare-2.33.0/tests/test_PyViCareDeviceConfig.py +0 -90
- pyvicare-2.33.0/tests/test_PyViCareExceptions.py +0 -29
- pyvicare-2.33.0/tests/test_PyViCareService.py +0 -39
- pyvicare-2.33.0/tests/test_Solar.py +0 -39
- pyvicare-2.33.0/tests/test_TestForMissingProperties.py +0 -157
- pyvicare-2.33.0/tests/test_Utils.py +0 -11
- pyvicare-2.33.0/tests/test_ViCareOAuthManager.py +0 -79
- pyvicare-2.33.0/tests/test_VitoairFs300E.py +0 -31
- pyvicare-2.33.0/tests/test_Vitocal200.py +0 -115
- pyvicare-2.33.0/tests/test_Vitocal200S.py +0 -33
- pyvicare-2.33.0/tests/test_Vitocal222S.py +0 -20
- pyvicare-2.33.0/tests/test_Vitocal250A.py +0 -192
- pyvicare-2.33.0/tests/test_Vitocal300G.py +0 -73
- pyvicare-2.33.0/tests/test_Vitocaldens222F.py +0 -76
- pyvicare-2.33.0/tests/test_VitochargeVX3.py +0 -88
- pyvicare-2.33.0/tests/test_VitoconnectOpto1.py +0 -18
- pyvicare-2.33.0/tests/test_Vitodens100W.py +0 -37
- pyvicare-2.33.0/tests/test_Vitodens200W.py +0 -94
- pyvicare-2.33.0/tests/test_Vitodens200W_2.py +0 -99
- pyvicare-2.33.0/tests/test_Vitodens222W.py +0 -64
- pyvicare-2.33.0/tests/test_Vitodens300W.py +0 -62
- pyvicare-2.33.0/tests/test_Vitodens333F.py +0 -63
- pyvicare-2.33.0/tests/test_VitolaUniferral.py +0 -29
- pyvicare-2.33.0/tests/test_VitovalorPT2.py +0 -172
- pyvicare-2.33.0/tests/test_zigbee_zk03839.py +0 -18
- pyvicare-2.33.0/tests/test_zigbee_zk03840.py +0 -28
- {pyvicare-2.33.0 → pyvicare-2.34.0}/LICENSE +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCare.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareBrowserOAuthManager.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareCachedService.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareDevice.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareElectricalEnergySystem.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareFuelCell.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareGateway.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareGazBoiler.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareHeatCurveCalculation.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareHybrid.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareOAuthManager.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareOilBoiler.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCarePelletsBoiler.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareRadiatorActuator.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareRoomSensor.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/PyViCareUtils.py +0 -0
- {pyvicare-2.33.0 → pyvicare-2.34.0}/PyViCare/__init__.py +0 -0
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyViCare
|
|
3
|
-
Version: 2.
|
|
4
|
-
Summary: Library to communicate with the Viessmann ViCare API
|
|
5
|
-
Home-page: https://github.com/
|
|
3
|
+
Version: 2.34.0
|
|
4
|
+
Summary: Library to communicate with the Viessmann ViCare API.
|
|
5
|
+
Home-page: https://github.com/openviess/PyViCare
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Keywords: viessmann,vicare,api
|
|
6
8
|
Author: Simon Gillet
|
|
7
9
|
Author-email: mail+pyvicare@gillet.ninja
|
|
8
|
-
|
|
10
|
+
Maintainer: Christopher Fenner
|
|
11
|
+
Maintainer-email: fenner.christopher@gmail.com
|
|
12
|
+
Requires-Python: >=3.8,<4.0
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
9
14
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Natural Language :: English
|
|
10
16
|
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Dist: authlib (>1.2.0)
|
|
25
|
+
Requires-Dist: requests (>=2.31.0)
|
|
26
|
+
Project-URL: Bug Tracker, https://github.com/openviess/PyViCare/issues
|
|
27
|
+
Project-URL: Changelog, https://github.com/openviess/PyViCare/releases
|
|
28
|
+
Project-URL: Documentation, https://github.com/openviess/PyViCare
|
|
29
|
+
Project-URL: Repository, https://github.com/openviess/PyViCare
|
|
11
30
|
Description-Content-Type: text/markdown
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
Requires-Dist: Authlib>=1.2.0
|
|
14
31
|
|
|
15
32
|
# PyViCare
|
|
16
33
|
|
|
@@ -22,18 +39,18 @@ This library implements access to Viessmann devices by using the official API fr
|
|
|
22
39
|
|
|
23
40
|
## Breaking changes in version 2.8.x
|
|
24
41
|
|
|
25
|
-
- The circuit, burner (Gaz) and compressor (Heat Pump) is now
|
|
42
|
+
- The circuit, burner (Gaz) and compressor (Heat Pump) is now separated. Accessing the properties of the burner/compressor is moved from `device.circuits` to `device.burners` and `device.compressor`.
|
|
26
43
|
|
|
27
44
|
## Breaking changes in version 2.x
|
|
28
45
|
|
|
29
46
|
- The API to access your device changed to a general `PyViCare` class. Use this class to load all available devices.
|
|
30
|
-
- The API to access the heating circuit of the device has moved to the `Device` class. You can now access and iterate over all available circuits via `device.
|
|
47
|
+
- The API to access the heating circuit of the device has moved to the `Device` class. You can now access and iterate over all available circuits via `device.circuits`. This allows to easily see which properties are depending on the circuit.
|
|
31
48
|
|
|
32
49
|
See the example below for how you can use that.
|
|
33
50
|
|
|
34
51
|
## Breaking changes in version 1.x
|
|
35
52
|
|
|
36
|
-
- The versions prior to 1.x used an
|
|
53
|
+
- The versions prior to 1.x used an unofficial API which stopped working on July, 15th 2021. All users need to migrate to version 1.0.0 to continue using the API.
|
|
37
54
|
- Exception is raised if the library runs into a API rate limit. (See feature flag `raise_exception_on_rate_limit`)
|
|
38
55
|
- Exception is raised if an unsupported device feature is used. (See feature flag `raise_exception_on_not_supported_device_feature`)
|
|
39
56
|
- Python 3.4 is no longer supported.
|
|
@@ -163,7 +180,7 @@ Follow these steps to access the API in Postman:
|
|
|
163
180
|
|
|
164
181
|
## More different devices for test cases needed
|
|
165
182
|
|
|
166
|
-
In order to help ensuring making it easier to create more test cases you can run this code and make a pull request with the new test of your device type added. Your test should be
|
|
183
|
+
In order to help ensuring making it easier to create more test cases you can run this code and make a pull request with the new test of your device type added. Your test should be committed into [tests/response](tests/response) and named `<family><model>`.
|
|
167
184
|
|
|
168
185
|
The code to run to make this happen is below. This automatically removes "sensitive" information like installation id and serial numbers.
|
|
169
186
|
You can either replace default values or use the `PYVICARE_*` environment variables.
|
|
@@ -184,3 +201,4 @@ with open(f"dump.json", mode='w') as output:
|
|
|
184
201
|
output.write(vicare.devices[0].dump_secure())
|
|
185
202
|
|
|
186
203
|
```
|
|
204
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Feature flag to raise an exception in case of a non existing device feature.
|
|
2
2
|
# The flag should be fully removed in a later release.
|
|
3
|
-
# It allows
|
|
3
|
+
# It allows dependent libraries to gracefully migrate to the new behaviour
|
|
4
4
|
raise_exception_on_not_supported_device_feature = True
|
|
5
5
|
|
|
6
6
|
# Feature flag to raise exception if rate limit of the API is hit
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from abc import
|
|
2
|
+
from abc import abstractmethod
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
5
|
from authlib.integrations.base_client import TokenExpiredError, InvalidTokenError
|
|
@@ -27,7 +27,8 @@ class AbstractViCareOAuthManager:
|
|
|
27
27
|
def replace_session(self, new_session: OAuth2Session) -> None:
|
|
28
28
|
self.__oauth = new_session
|
|
29
29
|
|
|
30
|
-
@
|
|
30
|
+
@classmethod
|
|
31
|
+
@abstractmethod
|
|
31
32
|
def renewToken(self) -> None:
|
|
32
33
|
return
|
|
33
34
|
|
|
@@ -87,7 +87,8 @@ class PyViCareDeviceConfig:
|
|
|
87
87
|
(self.asGateway, r"E3_TCU10_x07", ["type:gateway;TCU300"]),
|
|
88
88
|
(self.asElectricalEnergySystem, r"E3_VitoCharge_03", ["type:ees"]),
|
|
89
89
|
(self.asVentilation, r"E3_ViAir", ["type:ventilation"]),
|
|
90
|
-
(self.asGateway, r"Heatbox1", ["type:gateway;VitoconnectOpto1"])
|
|
90
|
+
(self.asGateway, r"Heatbox1", ["type:gateway;VitoconnectOpto1"]),
|
|
91
|
+
(self.asGateway, r"Heatbox2", ["type:gateway;VitoconnectOpto2/OT2"])
|
|
91
92
|
]
|
|
92
93
|
|
|
93
94
|
for (creator_method, type_name, roles) in device_types:
|
|
@@ -21,11 +21,11 @@ class HeatPump(HeatingDevice):
|
|
|
21
21
|
|
|
22
22
|
@handleNotSupported
|
|
23
23
|
def getBufferMainTemperature(self):
|
|
24
|
-
return self.service.getProperty("heating.
|
|
24
|
+
return self.service.getProperty("heating.bufferCylinder.sensors.temperature.main")["properties"]['value']['value']
|
|
25
25
|
|
|
26
26
|
@handleNotSupported
|
|
27
27
|
def getBufferTopTemperature(self):
|
|
28
|
-
return self.service.getProperty("heating.
|
|
28
|
+
return self.service.getProperty("heating.bufferCylinder.sensors.temperature.top")["properties"]['value']['value']
|
|
29
29
|
|
|
30
30
|
# Power consumption for Heating:
|
|
31
31
|
@handleNotSupported
|
|
@@ -56,6 +56,23 @@ class HeatPump(HeatingDevice):
|
|
|
56
56
|
def getPowerSummaryConsumptionHeatingLastYear(self):
|
|
57
57
|
return self.service.getProperty("heating.power.consumption.summary.heating")["properties"]["lastYear"]["value"]
|
|
58
58
|
|
|
59
|
+
# Power consumption for Cooling:
|
|
60
|
+
@handleNotSupported
|
|
61
|
+
def getPowerConsumptionCoolingUnit(self):
|
|
62
|
+
return self.service.getProperty("heating.power.consumption.cooling")["properties"]["day"]["unit"]
|
|
63
|
+
|
|
64
|
+
@handleNotSupported
|
|
65
|
+
def getPowerConsumptionCoolingToday(self):
|
|
66
|
+
return self.service.getProperty("heating.power.consumption.cooling")["properties"]["day"]["value"][0]
|
|
67
|
+
|
|
68
|
+
@handleNotSupported
|
|
69
|
+
def getPowerConsumptionCoolingThisMonth(self):
|
|
70
|
+
return self.service.getProperty("heating.power.consumption.cooling")["properties"]["month"]["value"][0]
|
|
71
|
+
|
|
72
|
+
@handleNotSupported
|
|
73
|
+
def getPowerConsumptionCoolingThisYear(self):
|
|
74
|
+
return self.service.getProperty("heating.power.consumption.cooling")["properties"]["year"]["value"][0]
|
|
75
|
+
|
|
59
76
|
@handleNotSupported
|
|
60
77
|
def getPowerConsumptionUnit(self):
|
|
61
78
|
return self.service.getProperty("heating.power.consumption.total")["properties"]["day"]["unit"]
|
|
@@ -126,8 +143,7 @@ class HeatPump(HeatingDevice):
|
|
|
126
143
|
@handleNotSupported
|
|
127
144
|
def getAvailableVentilationPrograms(self):
|
|
128
145
|
available_programs = []
|
|
129
|
-
for program in ['basic', 'intensive', 'reduced', 'standard', 'standby', '
|
|
130
|
-
'holiday', 'holidayAtHome', 'levelFour', 'levelOne', 'levelThree', 'levelTwo', 'permanent', 'silent']:
|
|
146
|
+
for program in ['basic', 'intensive', 'reduced', 'standard', 'standby', 'holidayAtHome', 'permanent']:
|
|
131
147
|
with suppress(PyViCareNotSupportedFeatureError):
|
|
132
148
|
if self.service.getProperty(f"ventilation.operating.programs.{program}") is not None:
|
|
133
149
|
available_programs.append(program)
|
|
@@ -68,13 +68,13 @@ class HeatingDevice(Device):
|
|
|
68
68
|
|
|
69
69
|
@handleNotSupported
|
|
70
70
|
def getHotWaterStorageTemperatureTop(self):
|
|
71
|
-
return self.service.getProperty("heating.dhw.sensors.temperature.
|
|
71
|
+
return self.service.getProperty("heating.dhw.sensors.temperature.dhwCylinder.top")["properties"]["value"][
|
|
72
72
|
"value"]
|
|
73
73
|
|
|
74
74
|
@handleNotSupported
|
|
75
75
|
def getHotWaterStorageTemperatureBottom(self):
|
|
76
76
|
return \
|
|
77
|
-
self.service.getProperty("heating.dhw.sensors.temperature.
|
|
77
|
+
self.service.getProperty("heating.dhw.sensors.temperature.dhwCylinder.bottom")["properties"]["value"][
|
|
78
78
|
"value"]
|
|
79
79
|
|
|
80
80
|
@handleNotSupported
|
|
@@ -115,7 +115,7 @@ class HeatingDevice(Device):
|
|
|
115
115
|
|
|
116
116
|
@handleNotSupported
|
|
117
117
|
def getDomesticHotWaterStorageTemperature(self):
|
|
118
|
-
return self.service.getProperty("heating.dhw.sensors.temperature.
|
|
118
|
+
return self.service.getProperty("heating.dhw.sensors.temperature.dhwCylinder")["properties"]["value"][
|
|
119
119
|
"value"]
|
|
120
120
|
|
|
121
121
|
@handleNotSupported
|
|
@@ -592,7 +592,7 @@ class HeatingCircuit(HeatingDeviceWithComponent):
|
|
|
592
592
|
'comfortHeating', 'dhwPrecedence', 'eco', 'external', 'fixed', 'forcedLastFromSchedule',
|
|
593
593
|
'frostprotection', 'holiday', 'holidayAtHome', 'manual', 'normal', 'normalCooling',
|
|
594
594
|
'normalCoolingEnergySaving', 'normalEnergySaving', 'normalHeating', 'reduced', 'reducedCooling',
|
|
595
|
-
'reducedCoolingEnergySaving', 'reducedEnergySaving', 'reducedHeating', 'standby'
|
|
595
|
+
'reducedCoolingEnergySaving', 'reducedEnergySaving', 'reducedHeating', 'standby']:
|
|
596
596
|
with suppress(PyViCareNotSupportedFeatureError):
|
|
597
597
|
if self.service.getProperty(
|
|
598
598
|
f"heating.circuits.{self.circuit}.operating.programs.{program}") is not None:
|
|
@@ -8,7 +8,6 @@ from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError
|
|
|
8
8
|
logger = logging.getLogger('ViCare')
|
|
9
9
|
logger.addHandler(logging.NullHandler())
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
def readFeature(entities, property_name):
|
|
13
12
|
feature = next(
|
|
14
13
|
(f for f in entities if f["feature"] == property_name), None)
|
|
@@ -18,22 +17,18 @@ def readFeature(entities, property_name):
|
|
|
18
17
|
|
|
19
18
|
return feature
|
|
20
19
|
|
|
21
|
-
|
|
22
20
|
def hasRoles(requested_roles: List[str], existing_roles: List[str]) -> bool:
|
|
23
21
|
return len(requested_roles) > 0 and set(requested_roles).issubset(set(existing_roles))
|
|
24
22
|
|
|
25
|
-
|
|
26
23
|
def buildSetPropertyUrl(accessor, property_name, action):
|
|
27
24
|
return f'/features/installations/{accessor.id}/gateways/{accessor.serial}/devices/{accessor.device_id}/features/{property_name}/commands/{action}'
|
|
28
25
|
|
|
29
|
-
|
|
30
26
|
class ViCareDeviceAccessor:
|
|
31
27
|
def __init__(self, _id: int, serial: str, device_id: str) -> None:
|
|
32
28
|
self.id = _id
|
|
33
29
|
self.serial = serial
|
|
34
30
|
self.device_id = device_id
|
|
35
31
|
|
|
36
|
-
|
|
37
32
|
class ViCareService:
|
|
38
33
|
def __init__(self, oauth_manager: AbstractViCareOAuthManager, accessor: ViCareDeviceAccessor, roles: List[str]) -> None:
|
|
39
34
|
self.oauth_manager = oauth_manager
|
|
@@ -49,12 +44,11 @@ class ViCareService:
|
|
|
49
44
|
return f'/features/installations/{self.accessor.id}/gateways/{self.accessor.serial}/features/{property_name}'
|
|
50
45
|
return f'/features/installations/{self.accessor.id}/gateways/{self.accessor.serial}/devices/{self.accessor.device_id}/features/{property_name}'
|
|
51
46
|
|
|
52
|
-
|
|
53
47
|
def hasRoles(self, requested_roles) -> bool:
|
|
54
48
|
return hasRoles(requested_roles, self.roles)
|
|
55
49
|
|
|
56
50
|
def _isGateway(self) -> bool:
|
|
57
|
-
return self.hasRoles(["type:gateway;VitoconnectOpto1"]) or self.hasRoles(["type:gateway;TCU300"])
|
|
51
|
+
return self.hasRoles(["type:gateway;VitoconnectOpto1"]) or self.hasRoles(["type:gateway;VitoconnectOpto2/OT2"]) or self.hasRoles(["type:gateway;TCU300"])
|
|
58
52
|
|
|
59
53
|
def setProperty(self, property_name: str, action: str, data: Any) -> Any:
|
|
60
54
|
url = buildSetPropertyUrl(
|
|
@@ -36,8 +36,7 @@ class VentilationDevice(Device):
|
|
|
36
36
|
@handleNotSupported
|
|
37
37
|
def getAvailablePrograms(self):
|
|
38
38
|
available_programs = []
|
|
39
|
-
for program in ['basic', 'intensive', 'reduced', 'standard', 'standby', '
|
|
40
|
-
'holiday', 'holidayAtHome', 'levelFour', 'levelOne', 'levelThree', 'levelTwo', 'permanent', 'silent']:
|
|
39
|
+
for program in ['basic', 'intensive', 'reduced', 'standard', 'standby', 'holidayAtHome', 'permanent']:
|
|
41
40
|
with suppress(PyViCareNotSupportedFeatureError):
|
|
42
41
|
if self.service.getProperty(f"ventilation.operating.programs.{program}") is not None:
|
|
43
42
|
available_programs.append(program)
|
|
@@ -8,18 +8,18 @@ This library implements access to Viessmann devices by using the official API fr
|
|
|
8
8
|
|
|
9
9
|
## Breaking changes in version 2.8.x
|
|
10
10
|
|
|
11
|
-
- The circuit, burner (Gaz) and compressor (Heat Pump) is now
|
|
11
|
+
- The circuit, burner (Gaz) and compressor (Heat Pump) is now separated. Accessing the properties of the burner/compressor is moved from `device.circuits` to `device.burners` and `device.compressor`.
|
|
12
12
|
|
|
13
13
|
## Breaking changes in version 2.x
|
|
14
14
|
|
|
15
15
|
- The API to access your device changed to a general `PyViCare` class. Use this class to load all available devices.
|
|
16
|
-
- The API to access the heating circuit of the device has moved to the `Device` class. You can now access and iterate over all available circuits via `device.
|
|
16
|
+
- The API to access the heating circuit of the device has moved to the `Device` class. You can now access and iterate over all available circuits via `device.circuits`. This allows to easily see which properties are depending on the circuit.
|
|
17
17
|
|
|
18
18
|
See the example below for how you can use that.
|
|
19
19
|
|
|
20
20
|
## Breaking changes in version 1.x
|
|
21
21
|
|
|
22
|
-
- The versions prior to 1.x used an
|
|
22
|
+
- The versions prior to 1.x used an unofficial API which stopped working on July, 15th 2021. All users need to migrate to version 1.0.0 to continue using the API.
|
|
23
23
|
- Exception is raised if the library runs into a API rate limit. (See feature flag `raise_exception_on_rate_limit`)
|
|
24
24
|
- Exception is raised if an unsupported device feature is used. (See feature flag `raise_exception_on_not_supported_device_feature`)
|
|
25
25
|
- Python 3.4 is no longer supported.
|
|
@@ -149,7 +149,7 @@ Follow these steps to access the API in Postman:
|
|
|
149
149
|
|
|
150
150
|
## More different devices for test cases needed
|
|
151
151
|
|
|
152
|
-
In order to help ensuring making it easier to create more test cases you can run this code and make a pull request with the new test of your device type added. Your test should be
|
|
152
|
+
In order to help ensuring making it easier to create more test cases you can run this code and make a pull request with the new test of your device type added. Your test should be committed into [tests/response](tests/response) and named `<family><model>`.
|
|
153
153
|
|
|
154
154
|
The code to run to make this happen is below. This automatically removes "sensitive" information like installation id and serial numbers.
|
|
155
155
|
You can either replace default values or use the `PYVICARE_*` environment variables.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "PyViCare"
|
|
3
|
+
version = "2.34.0"
|
|
4
|
+
description = "Library to communicate with the Viessmann ViCare API."
|
|
5
|
+
authors = [
|
|
6
|
+
"Simon Gillet <mail+pyvicare@gillet.ninja>"
|
|
7
|
+
]
|
|
8
|
+
maintainers = [
|
|
9
|
+
"Christopher Fenner <fenner.christopher@gmail.com>",
|
|
10
|
+
"Martin",
|
|
11
|
+
"Lukas Wöhrl",
|
|
12
|
+
]
|
|
13
|
+
license = "Apache-2.0"
|
|
14
|
+
readme = "README.md"
|
|
15
|
+
homepage = "https://github.com/openviess/PyViCare"
|
|
16
|
+
repository = "https://github.com/openviess/PyViCare"
|
|
17
|
+
documentation = "https://github.com/openviess/PyViCare"
|
|
18
|
+
keywords = [
|
|
19
|
+
"viessmann",
|
|
20
|
+
"vicare",
|
|
21
|
+
"api"
|
|
22
|
+
]
|
|
23
|
+
classifiers = [
|
|
24
|
+
"Intended Audience :: Developers",
|
|
25
|
+
"Natural Language :: English",
|
|
26
|
+
"Programming Language :: Python :: 3",
|
|
27
|
+
"License :: OSI Approved :: Apache Software License",
|
|
28
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
29
|
+
"Operating System :: OS Independent",
|
|
30
|
+
]
|
|
31
|
+
packages = [
|
|
32
|
+
{ include = "PyViCare", from = "." },
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[tool.poetry.urls]
|
|
36
|
+
"Bug Tracker" = "https://github.com/openviess/PyViCare/issues"
|
|
37
|
+
Changelog = "https://github.com/openviess/PyViCare/releases"
|
|
38
|
+
|
|
39
|
+
[tool.poetry.dependencies]
|
|
40
|
+
authlib = ">1.2.0"
|
|
41
|
+
python = "^3.8"
|
|
42
|
+
requests = ">=2.31.0"
|
|
43
|
+
|
|
44
|
+
[tool.poetry.group.dev.dependencies]
|
|
45
|
+
codespell = "^2.3.0"
|
|
46
|
+
mypy = "^1.11.2"
|
|
47
|
+
pylint = "^3.2.6"
|
|
48
|
+
pytest = "^8.3.2"
|
|
49
|
+
pytest-cov = "^5.0.0"
|
|
50
|
+
ruff = "^0.6.7"
|
|
51
|
+
types-requests = ">=2.31"
|
|
52
|
+
|
|
53
|
+
[tool.mypy]
|
|
54
|
+
# Specify the target platform details in config, so your developers are
|
|
55
|
+
# free to run mypy on Windows, Linux, or macOS and get consistent
|
|
56
|
+
# results.
|
|
57
|
+
platform = "linux"
|
|
58
|
+
python_version = "3.11"
|
|
59
|
+
|
|
60
|
+
# show error messages from unrelated files
|
|
61
|
+
follow_imports = "normal"
|
|
62
|
+
|
|
63
|
+
# suppress errors about unsatisfied imports
|
|
64
|
+
ignore_missing_imports = true
|
|
65
|
+
|
|
66
|
+
# be strict
|
|
67
|
+
check_untyped_defs = true
|
|
68
|
+
disallow_any_generics = true
|
|
69
|
+
disallow_incomplete_defs = true
|
|
70
|
+
disallow_subclassing_any = true
|
|
71
|
+
disallow_untyped_calls = true
|
|
72
|
+
disallow_untyped_decorators = true
|
|
73
|
+
disallow_untyped_defs = true
|
|
74
|
+
no_implicit_optional = true
|
|
75
|
+
strict_optional = true
|
|
76
|
+
warn_incomplete_stub = true
|
|
77
|
+
warn_no_return = true
|
|
78
|
+
warn_redundant_casts = true
|
|
79
|
+
warn_return_any = true
|
|
80
|
+
warn_unused_configs = true
|
|
81
|
+
warn_unused_ignores = true
|
|
82
|
+
|
|
83
|
+
[[tool.mypy.overrides]]
|
|
84
|
+
module = "authlib.*"
|
|
85
|
+
ignore_missing_imports = true
|
|
86
|
+
|
|
87
|
+
[tool.pylint."MESSAGES CONTROL"]
|
|
88
|
+
disable = [
|
|
89
|
+
"duplicate-code",
|
|
90
|
+
"fixme",
|
|
91
|
+
"line-too-long",
|
|
92
|
+
"invalid-name",
|
|
93
|
+
"too-many-public-methods",
|
|
94
|
+
"too-few-public-methods",
|
|
95
|
+
# FIXME:
|
|
96
|
+
"arguments-differ",
|
|
97
|
+
"attribute-defined-outside-init",
|
|
98
|
+
"bad-classmethod-argument",
|
|
99
|
+
"chained-comparison",
|
|
100
|
+
"consider-merging-isinstance",
|
|
101
|
+
"consider-using-dict-items",
|
|
102
|
+
"consider-using-generator",
|
|
103
|
+
"deprecated-decorator",
|
|
104
|
+
"missing-class-docstring",
|
|
105
|
+
"missing-function-docstring",
|
|
106
|
+
"missing-module-docstring",
|
|
107
|
+
"missing-timeout",
|
|
108
|
+
"raise-missing-from",
|
|
109
|
+
"unspecified-encoding",
|
|
110
|
+
"useless-object-inheritance",
|
|
111
|
+
"useless-parent-delegation",
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
[build-system]
|
|
115
|
+
build-backend = "poetry.core.masonry.api"
|
|
116
|
+
requires = ["poetry-core>=1.0.0"]
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: PyViCare
|
|
3
|
-
Version: 2.33.0
|
|
4
|
-
Summary: Library to communicate with the Viessmann ViCare API
|
|
5
|
-
Home-page: https://github.com/somm15/PyViCare
|
|
6
|
-
Author: Simon Gillet
|
|
7
|
-
Author-email: mail+pyvicare@gillet.ninja
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
Requires-Dist: Authlib>=1.2.0
|
|
14
|
-
|
|
15
|
-
# PyViCare
|
|
16
|
-
|
|
17
|
-
This library implements access to Viessmann devices by using the official API from the [Viessmann Developer Portal](https://developer.viessmann.com/).
|
|
18
|
-
|
|
19
|
-
## Breaking changes in version 2.27.x
|
|
20
|
-
|
|
21
|
-
- Some base classes have been renamed to provide a better support for non heating devices. See [PR #307](https://github.com/somm15/PyViCare/pull/307)
|
|
22
|
-
|
|
23
|
-
## Breaking changes in version 2.8.x
|
|
24
|
-
|
|
25
|
-
- The circuit, burner (Gaz) and compressor (Heat Pump) is now separted. Accessing the properties of the burner/compressor is moved from `device.curcuits` to `device.burners` and `device.compressor`.
|
|
26
|
-
|
|
27
|
-
## Breaking changes in version 2.x
|
|
28
|
-
|
|
29
|
-
- The API to access your device changed to a general `PyViCare` class. Use this class to load all available devices.
|
|
30
|
-
- The API to access the heating circuit of the device has moved to the `Device` class. You can now access and iterate over all available circuits via `device.curcuits`. This allows to easily see which properties are depending on the circuit.
|
|
31
|
-
|
|
32
|
-
See the example below for how you can use that.
|
|
33
|
-
|
|
34
|
-
## Breaking changes in version 1.x
|
|
35
|
-
|
|
36
|
-
- The versions prior to 1.x used an inofficial API which stopped working on July, 15th 2021. All users need to migrate to version 1.0.0 to continue using the API.
|
|
37
|
-
- Exception is raised if the library runs into a API rate limit. (See feature flag `raise_exception_on_rate_limit`)
|
|
38
|
-
- Exception is raised if an unsupported device feature is used. (See feature flag `raise_exception_on_not_supported_device_feature`)
|
|
39
|
-
- Python 3.4 is no longer supported.
|
|
40
|
-
- Python 3.9 is now supported.
|
|
41
|
-
|
|
42
|
-
## Prerequisites
|
|
43
|
-
|
|
44
|
-
To use PyViCare, every user has to register and create their personal API client. Follow these steps to create your client:
|
|
45
|
-
|
|
46
|
-
1. Login to the [Viessmann Developer Portal](https://app.developer.viessmann.com/) with **your existing ViCare app username/password**.
|
|
47
|
-
2. On the developer dashboard click *add* in the *clients* section.
|
|
48
|
-
3. Create a new client using following data:
|
|
49
|
-
- Name: PyViCare
|
|
50
|
-
- Google reCAPTCHA: Disabled
|
|
51
|
-
- Redirect URIs: `vicare://oauth-callback/everest`
|
|
52
|
-
4. Copy the `Client ID` to use in your code. Pass it as constructor parameter to the device.
|
|
53
|
-
|
|
54
|
-
Please note that not all properties from older versions and the ViCare mobile app are available in the new API. Missing properties were removed and might be added later if they are available again.
|
|
55
|
-
|
|
56
|
-
## Help
|
|
57
|
-
|
|
58
|
-
We need help testing and improving PyViCare, since the maintainers only have specific types of heating systems. For bugs, questions or feature requests join the [PyViCare channel on Discord](https://discord.gg/aM3SqCD88f) or create an issue in this repository.
|
|
59
|
-
|
|
60
|
-
## Device Features / Errors
|
|
61
|
-
|
|
62
|
-
Depending on the device, some features are not available/supported. This results in a raising of a `PyViCareNotSupportedFeatureError` if the dedicated method is called. This is most likely not a bug, but a limitation of the device itself.
|
|
63
|
-
|
|
64
|
-
Tip: You can use Pythons [contextlib.suppress](https://docs.python.org/3/library/contextlib.html#contextlib.suppress) to handle it gracefully.
|
|
65
|
-
|
|
66
|
-
## Types of heatings
|
|
67
|
-
|
|
68
|
-
- Use `asGazBoiler` for gas heatings
|
|
69
|
-
- Use `asHeatPump` for heat pumps
|
|
70
|
-
- Use `asFuelCell` for fuel cells
|
|
71
|
-
- Use `asPelletsBoiler` for pellets heatings
|
|
72
|
-
- Use `asOilBoiler` for oil heatings
|
|
73
|
-
- Use `asHybridDevice` for gas/heat pump hybrid heatings
|
|
74
|
-
|
|
75
|
-
## Basic Usage:
|
|
76
|
-
|
|
77
|
-
```python
|
|
78
|
-
import sys
|
|
79
|
-
import logging
|
|
80
|
-
from PyViCare.PyViCare import PyViCare
|
|
81
|
-
|
|
82
|
-
client_id = "INSERT CLIENT ID"
|
|
83
|
-
email = "email@domain"
|
|
84
|
-
password = "password"
|
|
85
|
-
|
|
86
|
-
vicare = PyViCare()
|
|
87
|
-
vicare.initWithCredentials(email, password, client_id, "token.save")
|
|
88
|
-
device = vicare.devices[0]
|
|
89
|
-
print(device.getModel())
|
|
90
|
-
print("Online" if device.isOnline() else "Offline")
|
|
91
|
-
|
|
92
|
-
t = device.asAutoDetectDevice()
|
|
93
|
-
print(t.getDomesticHotWaterConfiguredTemperature())
|
|
94
|
-
print(t.getDomesticHotWaterStorageTemperature())
|
|
95
|
-
print(t.getOutsideTemperature())
|
|
96
|
-
print(t.getRoomTemperature())
|
|
97
|
-
print(t.getBoilerTemperature())
|
|
98
|
-
print(t.setDomesticHotWaterTemperature(59))
|
|
99
|
-
|
|
100
|
-
circuit = t.circuits[0] #select heating circuit
|
|
101
|
-
|
|
102
|
-
print(circuit.getSupplyTemperature())
|
|
103
|
-
print(circuit.getHeatingCurveShift())
|
|
104
|
-
print(circuit.getHeatingCurveSlope())
|
|
105
|
-
|
|
106
|
-
print(circuit.getActiveProgram())
|
|
107
|
-
print(circuit.getPrograms())
|
|
108
|
-
|
|
109
|
-
print(circuit.getCurrentDesiredTemperature())
|
|
110
|
-
print(circuit.getDesiredTemperatureForProgram("comfort"))
|
|
111
|
-
print(circuit.getActiveMode())
|
|
112
|
-
|
|
113
|
-
print(circuit.getDesiredTemperatureForProgram("comfort"))
|
|
114
|
-
print(circuit.setProgramTemperature("comfort",21))
|
|
115
|
-
print(circuit.activateProgram("comfort"))
|
|
116
|
-
print(circuit.deactivateComfort())
|
|
117
|
-
|
|
118
|
-
burner = t.burners[0] #select burner
|
|
119
|
-
print(burner.getActive())
|
|
120
|
-
|
|
121
|
-
compressor = t.compressors[0] #select compressor
|
|
122
|
-
print(compressor.getActive())
|
|
123
|
-
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## API Usage in Postman
|
|
127
|
-
|
|
128
|
-
Follow these steps to access the API in Postman:
|
|
129
|
-
|
|
130
|
-
1. Create an access token in the `Authorization` tab with type `OAuth 2.0` and following inputs:
|
|
131
|
-
|
|
132
|
-
- Token Name: `PyViCare`
|
|
133
|
-
- Grant Type: `Authorization Code (With PKCE)`
|
|
134
|
-
- Callback URL: `vicare://oauth-callback/everest`
|
|
135
|
-
- Authorize using browser: Disabled
|
|
136
|
-
- Auth URL: `https://iam.viessmann.com/idp/v3/authorize`
|
|
137
|
-
- Access Token URL: `https://iam.viessmann.com/idp/v3/token`
|
|
138
|
-
- Client ID: Your personal Client ID created in the developer portal.
|
|
139
|
-
- Client Secret: Blank
|
|
140
|
-
- Code Challenge Method: `SHA-256`
|
|
141
|
-
- Code Veriefier: Blank
|
|
142
|
-
- Scope: `IoT User`
|
|
143
|
-
- State: Blank
|
|
144
|
-
- Client Authentication: `Send client credentials in body`.
|
|
145
|
-
|
|
146
|
-
A login popup will open. Enter your ViCare username and password.
|
|
147
|
-
|
|
148
|
-
2. Use this URL to access your `installationId`, `gatewaySerial` and `deviceId`:
|
|
149
|
-
|
|
150
|
-
`https://api.viessmann.com/iot/v1/equipment/installations?includeGateways=true`
|
|
151
|
-
|
|
152
|
-
- `installationId` is `data[0].id`
|
|
153
|
-
- `gatewaySerial` is `data[0].gateways[0].serial`
|
|
154
|
-
- `deviceId` is `data[0].gateways[0].devices[0].id`
|
|
155
|
-
|
|
156
|
-
3. Use above data to replace `{installationId}`, `{gatewaySerial}` and `{deviceId}` in this URL to investigate the Viessmann API:
|
|
157
|
-
|
|
158
|
-
`https://api.viessmann.com/iot/v1/features/installations/{installationId}/gateways/{gatewaySerial}/devices/{deviceId}/features`
|
|
159
|
-
|
|
160
|
-
## Rate Limits
|
|
161
|
-
|
|
162
|
-
[Due to latest changes in the Viessmann API](https://www.viessmann-community.com/t5/Konnektivitaet/Q-amp-A-Viessmann-API/td-p/127660) rate limits can be hit. In that case a `PyViCareRateLimitError` is raised. You can read from the error (`limitResetDate`) when the rate limit is reset.
|
|
163
|
-
|
|
164
|
-
## More different devices for test cases needed
|
|
165
|
-
|
|
166
|
-
In order to help ensuring making it easier to create more test cases you can run this code and make a pull request with the new test of your device type added. Your test should be commited into [tests/response](tests/response) and named `<family><model>`.
|
|
167
|
-
|
|
168
|
-
The code to run to make this happen is below. This automatically removes "sensitive" information like installation id and serial numbers.
|
|
169
|
-
You can either replace default values or use the `PYVICARE_*` environment variables.
|
|
170
|
-
|
|
171
|
-
```python
|
|
172
|
-
import sys
|
|
173
|
-
import os
|
|
174
|
-
from PyViCare.PyViCare import PyViCare
|
|
175
|
-
|
|
176
|
-
client_id = os.getenv("PYVICARE_CLIENT_ID", "INSERT CLIENT_ID")
|
|
177
|
-
email = os.getenv("PYVICARE_EMAIL", "email@domain")
|
|
178
|
-
password = os.getenv("PYVICARE_PASSWORD", "password")
|
|
179
|
-
|
|
180
|
-
vicare = PyViCare()
|
|
181
|
-
vicare.initWithCredentials(email, password, client_id, "token.save")
|
|
182
|
-
|
|
183
|
-
with open(f"dump.json", mode='w') as output:
|
|
184
|
-
output.write(vicare.devices[0].dump_secure())
|
|
185
|
-
|
|
186
|
-
```
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
LICENSE
|
|
2
|
-
README.md
|
|
3
|
-
setup.py
|
|
4
|
-
PyViCare/Feature.py
|
|
5
|
-
PyViCare/PyViCare.py
|
|
6
|
-
PyViCare/PyViCareAbstractOAuthManager.py
|
|
7
|
-
PyViCare/PyViCareBrowserOAuthManager.py
|
|
8
|
-
PyViCare/PyViCareCachedService.py
|
|
9
|
-
PyViCare/PyViCareDevice.py
|
|
10
|
-
PyViCare/PyViCareDeviceConfig.py
|
|
11
|
-
PyViCare/PyViCareElectricalEnergySystem.py
|
|
12
|
-
PyViCare/PyViCareFuelCell.py
|
|
13
|
-
PyViCare/PyViCareGateway.py
|
|
14
|
-
PyViCare/PyViCareGazBoiler.py
|
|
15
|
-
PyViCare/PyViCareHeatCurveCalculation.py
|
|
16
|
-
PyViCare/PyViCareHeatPump.py
|
|
17
|
-
PyViCare/PyViCareHeatingDevice.py
|
|
18
|
-
PyViCare/PyViCareHybrid.py
|
|
19
|
-
PyViCare/PyViCareOAuthManager.py
|
|
20
|
-
PyViCare/PyViCareOilBoiler.py
|
|
21
|
-
PyViCare/PyViCarePelletsBoiler.py
|
|
22
|
-
PyViCare/PyViCareRadiatorActuator.py
|
|
23
|
-
PyViCare/PyViCareRoomSensor.py
|
|
24
|
-
PyViCare/PyViCareService.py
|
|
25
|
-
PyViCare/PyViCareUtils.py
|
|
26
|
-
PyViCare/PyViCareVentilationDevice.py
|
|
27
|
-
PyViCare/__init__.py
|
|
28
|
-
PyViCare.egg-info/PKG-INFO
|
|
29
|
-
PyViCare.egg-info/SOURCES.txt
|
|
30
|
-
PyViCare.egg-info/dependency_links.txt
|
|
31
|
-
PyViCare.egg-info/requires.txt
|
|
32
|
-
PyViCare.egg-info/top_level.txt
|
|
33
|
-
tests/test_E3_TCU300_ethernet.py
|
|
34
|
-
tests/test_GenericDevice.py
|
|
35
|
-
tests/test_Integration.py
|
|
36
|
-
tests/test_PyViCareCachedService.py
|
|
37
|
-
tests/test_PyViCareDeviceConfig.py
|
|
38
|
-
tests/test_PyViCareExceptions.py
|
|
39
|
-
tests/test_PyViCareService.py
|
|
40
|
-
tests/test_Solar.py
|
|
41
|
-
tests/test_TestForMissingProperties.py
|
|
42
|
-
tests/test_Utils.py
|
|
43
|
-
tests/test_ViCareOAuthManager.py
|
|
44
|
-
tests/test_VitoairFs300E.py
|
|
45
|
-
tests/test_Vitocal200.py
|
|
46
|
-
tests/test_Vitocal200S.py
|
|
47
|
-
tests/test_Vitocal222S.py
|
|
48
|
-
tests/test_Vitocal250A.py
|
|
49
|
-
tests/test_Vitocal300G.py
|
|
50
|
-
tests/test_Vitocaldens222F.py
|
|
51
|
-
tests/test_VitochargeVX3.py
|
|
52
|
-
tests/test_VitoconnectOpto1.py
|
|
53
|
-
tests/test_Vitodens100W.py
|
|
54
|
-
tests/test_Vitodens200W.py
|
|
55
|
-
tests/test_Vitodens200W_2.py
|
|
56
|
-
tests/test_Vitodens222W.py
|
|
57
|
-
tests/test_Vitodens300W.py
|
|
58
|
-
tests/test_Vitodens333F.py
|
|
59
|
-
tests/test_VitolaUniferral.py
|
|
60
|
-
tests/test_VitovalorPT2.py
|
|
61
|
-
tests/test_zigbee_zk03839.py
|
|
62
|
-
tests/test_zigbee_zk03840.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Authlib>=1.2.0
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
PyViCare
|
pyvicare-2.33.0/setup.cfg
DELETED