python-tado 0.18.14__tar.gz → 0.18.15__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.
- {python_tado-0.18.14/python_tado.egg-info → python_tado-0.18.15}/PKG-INFO +1 -1
- python_tado-0.18.15/PyTado/__init__.py +6 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/http.py +5 -1
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/api/my_tado.py +19 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/interface.py +4 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/pyproject.toml +1 -1
- {python_tado-0.18.14 → python_tado-0.18.15/python_tado.egg-info}/PKG-INFO +1 -1
- {python_tado-0.18.14 → python_tado-0.18.15}/tests/test_http.py +21 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/tests/test_my_tado.py +49 -0
- python_tado-0.18.14/PyTado/__init__.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/AUTHORS +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/LICENSE +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/__main__.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/const.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/exceptions.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/__init__.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/api/__init__.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/api/hops_tado.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/logger.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/zone/__init__.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/zone/hops_zone.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/zone/my_zone.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/README.md +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/SOURCES.txt +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/dependency_links.txt +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/entry_points.txt +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/not-zip-safe +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/requires.txt +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/top_level.txt +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/setup.cfg +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/tests/test_hops_zone.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/tests/test_my_zone.py +0 -0
- {python_tado-0.18.14 → python_tado-0.18.15}/tests/test_tado_interface.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-tado
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.15
|
|
4
4
|
Summary: PyTado from chrism0dwk, modfied by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon, FilBr, nikilase, albertomontesg, Moritz-Schmidt, palazzem
|
|
5
5
|
Author-email: Chris Jewell <chrism0dwk@gmail.com>, "w.malgadey" <w.malgadey@gmail.com>, FilBr <filippo.barba@protonmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -19,6 +19,7 @@ from urllib.parse import urlencode
|
|
|
19
19
|
|
|
20
20
|
import requests
|
|
21
21
|
|
|
22
|
+
from PyTado import __version__
|
|
22
23
|
from PyTado.const import CLIENT_ID_DEVICE
|
|
23
24
|
from PyTado.exceptions import TadoException, TadoWrongCredentialsException
|
|
24
25
|
from PyTado.logger import Logger
|
|
@@ -156,6 +157,7 @@ class Http:
|
|
|
156
157
|
saved_refresh_token: str | None = None,
|
|
157
158
|
http_session: requests.Session | None = None,
|
|
158
159
|
debug: bool = False,
|
|
160
|
+
user_agent: str | None = None,
|
|
159
161
|
) -> None:
|
|
160
162
|
"""
|
|
161
163
|
Initialize the HTTP client for interacting with the Tado API.
|
|
@@ -168,6 +170,8 @@ class Http:
|
|
|
168
170
|
http_session (requests.Session | None): An optional pre-configured HTTP session.
|
|
169
171
|
If None, a new session will be created.
|
|
170
172
|
debug (bool): If True, enables debug logging. Defaults to False.
|
|
173
|
+
user_agent (str | None): Optional user-agent header to use for the HTTP requests.
|
|
174
|
+
If None, a default user-agent PyTado/<PyTado-version> will be used.
|
|
171
175
|
|
|
172
176
|
Returns:
|
|
173
177
|
None
|
|
@@ -181,7 +185,7 @@ class Http:
|
|
|
181
185
|
self._refresh_at = datetime.now(timezone.utc) + timedelta(minutes=10)
|
|
182
186
|
self._session = http_session or self._create_session()
|
|
183
187
|
self._session.hooks["response"].append(self._log_response)
|
|
184
|
-
self._headers = {"Referer": "https://app.tado.com/"}
|
|
188
|
+
self._headers = {"Referer": "https://app.tado.com/", "user-agent": user_agent or f"PyTado/{__version__}"}
|
|
185
189
|
|
|
186
190
|
self._user_code: str | None = None
|
|
187
191
|
self._device_verification_url: str | None = None
|
|
@@ -526,6 +526,25 @@ class Tado:
|
|
|
526
526
|
|
|
527
527
|
return self._http.request(request)
|
|
528
528
|
|
|
529
|
+
def get_eiq_consumption_overview(self, date=datetime.datetime.now().strftime("%Y-%m")):
|
|
530
|
+
"""
|
|
531
|
+
Get consumption overview data for a specific month
|
|
532
|
+
|
|
533
|
+
Args:
|
|
534
|
+
date (str): The year-month to get the consumption overview for.
|
|
535
|
+
|
|
536
|
+
Returns:
|
|
537
|
+
dict: Consumption overview data for the specified month
|
|
538
|
+
"""
|
|
539
|
+
|
|
540
|
+
request = TadoRequest()
|
|
541
|
+
request.command = "consumptionOverview"
|
|
542
|
+
request.action = Action.GET
|
|
543
|
+
request.endpoint = Endpoint.EIQ
|
|
544
|
+
request.params = {"month": f"{date}"}
|
|
545
|
+
|
|
546
|
+
return self._http.request(request)
|
|
547
|
+
|
|
529
548
|
def set_eiq_meter_readings(self, date=datetime.datetime.now().strftime("%Y-%m-%d"), reading=0):
|
|
530
549
|
"""
|
|
531
550
|
Send Meter Readings to Tado, date format is YYYY-MM-DD, reading is without decimals
|
|
@@ -55,6 +55,7 @@ class Tado:
|
|
|
55
55
|
saved_refresh_token: str | None = None,
|
|
56
56
|
http_session: requests.Session | None = None,
|
|
57
57
|
debug: bool = False,
|
|
58
|
+
user_agent: str | None = None,
|
|
58
59
|
):
|
|
59
60
|
"""
|
|
60
61
|
Initializes the interface class.
|
|
@@ -68,6 +69,8 @@ class Tado:
|
|
|
68
69
|
requests (can be used in unit tests).
|
|
69
70
|
Defaults to None.
|
|
70
71
|
debug (bool, optional): Flag to enable or disable debug mode. Defaults to False.
|
|
72
|
+
user_agent (str | None): Optional user-agent header to use for the HTTP requests.
|
|
73
|
+
If None, a default user-agent PyTado/<PyTado-version> will be used.
|
|
71
74
|
"""
|
|
72
75
|
|
|
73
76
|
self._http = Http(
|
|
@@ -75,6 +78,7 @@ class Tado:
|
|
|
75
78
|
saved_refresh_token=saved_refresh_token,
|
|
76
79
|
http_session=http_session,
|
|
77
80
|
debug=debug,
|
|
81
|
+
user_agent=user_agent,
|
|
78
82
|
)
|
|
79
83
|
self._api: API.Tado | API.TadoX | None = None
|
|
80
84
|
self._debug = debug
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-tado"
|
|
7
|
-
version = "0.18.
|
|
7
|
+
version = "0.18.15"
|
|
8
8
|
description = "PyTado from chrism0dwk, modfied by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon, FilBr, nikilase, albertomontesg, Moritz-Schmidt, palazzem"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Chris Jewell", email = "chrism0dwk@gmail.com" },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-tado
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.15
|
|
4
4
|
Summary: PyTado from chrism0dwk, modfied by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon, FilBr, nikilase, albertomontesg, Moritz-Schmidt, palazzem
|
|
5
5
|
Author-email: Chris Jewell <chrism0dwk@gmail.com>, "w.malgadey" <w.malgadey@gmail.com>, FilBr <filippo.barba@protonmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -124,6 +124,27 @@ class TestHttp(unittest.TestCase):
|
|
|
124
124
|
self.assertEqual(instance._id, 1234)
|
|
125
125
|
self.assertEqual(instance.is_x_line, True)
|
|
126
126
|
|
|
127
|
+
@responses.activate
|
|
128
|
+
def test_user_agent(self):
|
|
129
|
+
"""Test that the we set the correct user-agent."""
|
|
130
|
+
responses.replace(
|
|
131
|
+
responses.GET,
|
|
132
|
+
"https://my.tado.com/api/v2/homes/1234/",
|
|
133
|
+
json=json.loads(
|
|
134
|
+
common.load_fixture(
|
|
135
|
+
"home_1234/tadov2.my_api_v2_home_state.json"
|
|
136
|
+
)
|
|
137
|
+
),
|
|
138
|
+
match=[matchers.header_matcher({"user-agent": "MyCustomAgent/1.0"})],
|
|
139
|
+
status=200,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
instance = Http(debug=True, user_agent="MyCustomAgent/1.0")
|
|
143
|
+
instance.device_activation()
|
|
144
|
+
|
|
145
|
+
# Verify that the login was successful
|
|
146
|
+
self.assertEqual(instance._id, 1234)
|
|
147
|
+
|
|
127
148
|
@responses.activate
|
|
128
149
|
def test_refresh_token_success(self):
|
|
129
150
|
"""Test that the refresh token is successfully updated."""
|
|
@@ -30,6 +30,7 @@ class TadoTestCase(unittest.TestCase):
|
|
|
30
30
|
self.http = Http()
|
|
31
31
|
self.tado_client = Tado(self.http)
|
|
32
32
|
|
|
33
|
+
|
|
33
34
|
def test_home_set_to_manual_mode(
|
|
34
35
|
self,
|
|
35
36
|
):
|
|
@@ -95,3 +96,51 @@ class TadoTestCase(unittest.TestCase):
|
|
|
95
96
|
assert self.tado_client._http.request.called
|
|
96
97
|
assert running_times["lastUpdated"] == "2023-08-05T19:50:21Z"
|
|
97
98
|
assert running_times["runningTimes"][0]["zones"][0]["id"] == 1
|
|
99
|
+
|
|
100
|
+
def get_eiq_consumption_overview(self):
|
|
101
|
+
"""Test the get_eiq_consumption_overview method."""
|
|
102
|
+
|
|
103
|
+
with mock.patch(
|
|
104
|
+
"PyTado.http.Http.request",
|
|
105
|
+
return_value=json.loads(common.load_fixture("consumption_overview.json")),
|
|
106
|
+
):
|
|
107
|
+
#consumption = self.tado_client.get_eiq_consumption_overview("2024", "03", "HUN")
|
|
108
|
+
consumption = self.tado_client.get_eiq_consumption_overview("2024-03")
|
|
109
|
+
|
|
110
|
+
# Verify API call was made
|
|
111
|
+
assert self.tado_client._http.request.called
|
|
112
|
+
|
|
113
|
+
# Verify summary data
|
|
114
|
+
assert consumption["summary"]["consumption"] == 10.575
|
|
115
|
+
assert consumption["summary"]["unit"] == "m3"
|
|
116
|
+
assert consumption["summary"]["tariff"]["unitPriceInCents"] == 9.18
|
|
117
|
+
|
|
118
|
+
# Verify monthly data
|
|
119
|
+
monthly = consumption["graphConsumption"]["monthlyAggregation"][
|
|
120
|
+
"requestedMonth"
|
|
121
|
+
]
|
|
122
|
+
assert monthly["startDate"] == "2025-04-01"
|
|
123
|
+
assert monthly["endDate"] == "2025-04-10"
|
|
124
|
+
assert monthly["totalConsumption"] == 10.575
|
|
125
|
+
assert monthly["totalCostInCents"] == 1024.18
|
|
126
|
+
|
|
127
|
+
# Verify consumption comparison
|
|
128
|
+
comparison = consumption["consumptionComparison"]["consumption"]
|
|
129
|
+
assert comparison["comparedToMonthBefore"]["trend"] == "DECREASE"
|
|
130
|
+
assert comparison["comparedToMonthBefore"]["percentage"] == 65
|
|
131
|
+
assert comparison["comparedToYearBefore"]["trend"] == "INCREASE"
|
|
132
|
+
assert comparison["comparedToYearBefore"]["percentage"] == 71
|
|
133
|
+
|
|
134
|
+
# Verify room breakdown
|
|
135
|
+
rooms = consumption["roomBreakdown"]["requestedMonth"]["perRoom"]
|
|
136
|
+
assert len(rooms) == 7 # Verify total number of rooms
|
|
137
|
+
assert rooms[0]["name"] == "Schlafzimmer"
|
|
138
|
+
assert rooms[0]["consumption"] == 4.102
|
|
139
|
+
assert rooms[0]["costInCents"] == 397.27
|
|
140
|
+
|
|
141
|
+
# Verify heating insights
|
|
142
|
+
insights = consumption["heatingInsights"]
|
|
143
|
+
assert insights["heatingHours"]["trend"] == "DECREASE"
|
|
144
|
+
assert insights["heatingHours"]["diff"] == 181
|
|
145
|
+
assert insights["outsideTemperature"]["diff"] == 1
|
|
146
|
+
assert insights["awayHours"]["diff"] == 37
|
|
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
|