PyViCare 2.60.0__tar.gz → 2.60.2__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.60.0 → pyvicare-2.60.2}/PKG-INFO +1 -1
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCare.py +2 -2
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareOAuthManager.py +76 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/pyproject.toml +2 -1
- {pyvicare-2.60.0 → pyvicare-2.60.2}/LICENSE +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/Feature.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareAbstractOAuthManager.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareBrowserOAuthManager.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareCachedService.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareDevice.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareDeviceConfig.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareElectricalEnergySystem.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareFloorHeating.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareFuelCell.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareGateway.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareGazBoiler.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareHeatCurveCalculation.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareHeatPump.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareHeatingDevice.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareHybrid.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareOilBoiler.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCarePelletsBoiler.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareRadiatorActuator.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareRepeater.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareRoomControl.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareRoomSensor.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareService.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareUtils.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/PyViCareVentilationDevice.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/PyViCare/__init__.py +0 -0
- {pyvicare-2.60.0 → pyvicare-2.60.2}/README.md +0 -0
|
@@ -8,7 +8,7 @@ from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig
|
|
|
8
8
|
from PyViCare.PyViCareOAuthManager import ViCareOAuthManager
|
|
9
9
|
from PyViCare.PyViCareRoomControl import RoomControl
|
|
10
10
|
from PyViCare.PyViCareService import ViCareDeviceAccessor, ViCareService
|
|
11
|
-
from PyViCare.PyViCareUtils import PyViCareInvalidDataError
|
|
11
|
+
from PyViCare.PyViCareUtils import PyViCareInvalidDataError
|
|
12
12
|
|
|
13
13
|
logger = logging.getLogger(__name__)
|
|
14
14
|
logger.addHandler(logging.NullHandler())
|
|
@@ -86,7 +86,7 @@ class PyViCare:
|
|
|
86
86
|
room_control = RoomControl(device_config.service)
|
|
87
87
|
try:
|
|
88
88
|
actor_map = room_control.buildActorRoomMap()
|
|
89
|
-
except
|
|
89
|
+
except Exception: # pylint: disable=broad-exception-caught
|
|
90
90
|
logger.debug("Could not build actor map for %s", device_config.getModel(), exc_info=True)
|
|
91
91
|
continue
|
|
92
92
|
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
3
|
import pickle
|
|
4
|
+
import warnings
|
|
4
5
|
from contextlib import suppress
|
|
5
6
|
from pickle import UnpicklingError
|
|
6
7
|
|
|
7
8
|
import requests
|
|
8
9
|
from authlib.common.security import generate_token
|
|
10
|
+
from authlib.integrations.base_client.errors import OAuthError
|
|
9
11
|
from authlib.integrations.requests_client import OAuth2Session
|
|
10
12
|
|
|
11
13
|
from PyViCare.PyViCareAbstractOAuthManager import (
|
|
12
14
|
AUTHORIZE_URL,
|
|
13
15
|
SCOPE_IOT,
|
|
16
|
+
SCOPE_OFFLINE_ACCESS,
|
|
14
17
|
SCOPE_USER,
|
|
15
18
|
TOKEN_URL,
|
|
16
19
|
AbstractViCareOAuthManager,
|
|
@@ -24,6 +27,79 @@ logger.addHandler(logging.NullHandler())
|
|
|
24
27
|
REDIRECT_URI = "vicare://oauth-callback/everest"
|
|
25
28
|
|
|
26
29
|
|
|
30
|
+
def obtain_token_via_basic_auth_pkce(
|
|
31
|
+
client_id: str, username: str, password: str
|
|
32
|
+
) -> dict[str, object]:
|
|
33
|
+
"""Obtain an OAuth2 token via PKCE auth-code flow with HTTP Basic auth.
|
|
34
|
+
|
|
35
|
+
.. deprecated::
|
|
36
|
+
One-shot migration helper for Home Assistant's password-to-OAuth2
|
|
37
|
+
migration (see home-assistant/core#165621). Scheduled for removal
|
|
38
|
+
once the migration window has closed. New code should use the
|
|
39
|
+
standard OAuth2 auth-code flow.
|
|
40
|
+
|
|
41
|
+
Viessmann's authorization endpoint accepts HTTP Basic auth and returns
|
|
42
|
+
the auth code in the redirect Location header (no browser involved).
|
|
43
|
+
Useful for one-shot migration from stored username/password to OAuth2,
|
|
44
|
+
so users don't need to re-authenticate interactively.
|
|
45
|
+
|
|
46
|
+
Requests scopes ``IoT`` and ``offline_access`` (sufficient for all
|
|
47
|
+
PyViCare API endpoints; ``offline_access`` is required to receive a
|
|
48
|
+
refresh token).
|
|
49
|
+
|
|
50
|
+
Returns the token dict (access_token, refresh_token, expires_at, etc.)
|
|
51
|
+
on success, or an empty dict on any failure (auth server unreachable,
|
|
52
|
+
credentials rejected, token exchange failed). Failures are logged at
|
|
53
|
+
WARNING level.
|
|
54
|
+
"""
|
|
55
|
+
warnings.warn(
|
|
56
|
+
"obtain_token_via_basic_auth_pkce is a one-shot migration helper "
|
|
57
|
+
"for Home Assistant's password-to-OAuth2 migration and is scheduled "
|
|
58
|
+
"for removal. New code should use the standard OAuth2 auth-code flow.",
|
|
59
|
+
DeprecationWarning,
|
|
60
|
+
stacklevel=2,
|
|
61
|
+
)
|
|
62
|
+
oauth = OAuth2Session(
|
|
63
|
+
client_id,
|
|
64
|
+
redirect_uri=REDIRECT_URI,
|
|
65
|
+
scope=[SCOPE_IOT, SCOPE_OFFLINE_ACCESS],
|
|
66
|
+
code_challenge_method="S256",
|
|
67
|
+
)
|
|
68
|
+
code_verifier = generate_token(48)
|
|
69
|
+
auth_url, _ = oauth.create_authorization_url(
|
|
70
|
+
AUTHORIZE_URL, code_verifier=code_verifier
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
response = requests.post(
|
|
75
|
+
auth_url,
|
|
76
|
+
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
|
77
|
+
auth=(username, password),
|
|
78
|
+
allow_redirects=False,
|
|
79
|
+
timeout=15,
|
|
80
|
+
)
|
|
81
|
+
except requests.RequestException:
|
|
82
|
+
logger.warning("Failed to reach Viessmann auth server")
|
|
83
|
+
return {}
|
|
84
|
+
|
|
85
|
+
if response.status_code != 302 or "Location" not in response.headers:
|
|
86
|
+
logger.warning("Basic-auth authorization failed")
|
|
87
|
+
return {}
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
oauth.fetch_token(
|
|
91
|
+
TOKEN_URL,
|
|
92
|
+
authorization_response=response.headers["Location"],
|
|
93
|
+
code_verifier=code_verifier,
|
|
94
|
+
timeout=15,
|
|
95
|
+
)
|
|
96
|
+
except (requests.RequestException, OAuthError, KeyError, ValueError):
|
|
97
|
+
logger.warning("Token exchange failed")
|
|
98
|
+
return {}
|
|
99
|
+
|
|
100
|
+
return dict(oauth.token)
|
|
101
|
+
|
|
102
|
+
|
|
27
103
|
class ViCareOAuthManager(AbstractViCareOAuthManager):
|
|
28
104
|
def __init__(self, username, password, client_id, token_file):
|
|
29
105
|
self.username = username
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "PyViCare"
|
|
3
|
-
version = "2.60.
|
|
3
|
+
version = "2.60.2"
|
|
4
4
|
description = "Library to communicate with the Viessmann ViCare API."
|
|
5
5
|
authors = [
|
|
6
6
|
"Simon Gillet <mail+pyvicare@gillet.ninja>"
|
|
@@ -27,6 +27,7 @@ classifiers = [
|
|
|
27
27
|
"Programming Language :: Python :: 3.11",
|
|
28
28
|
"Programming Language :: Python :: 3.12",
|
|
29
29
|
"Programming Language :: Python :: 3.13",
|
|
30
|
+
"Programming Language :: Python :: 3.14",
|
|
30
31
|
"Programming Language :: Python :: 3",
|
|
31
32
|
"License :: OSI Approved :: Apache Software License",
|
|
32
33
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
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
|
|
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
|