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.
Files changed (33) hide show
  1. {python_tado-0.18.14/python_tado.egg-info → python_tado-0.18.15}/PKG-INFO +1 -1
  2. python_tado-0.18.15/PyTado/__init__.py +6 -0
  3. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/http.py +5 -1
  4. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/api/my_tado.py +19 -0
  5. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/interface.py +4 -0
  6. {python_tado-0.18.14 → python_tado-0.18.15}/pyproject.toml +1 -1
  7. {python_tado-0.18.14 → python_tado-0.18.15/python_tado.egg-info}/PKG-INFO +1 -1
  8. {python_tado-0.18.14 → python_tado-0.18.15}/tests/test_http.py +21 -0
  9. {python_tado-0.18.14 → python_tado-0.18.15}/tests/test_my_tado.py +49 -0
  10. python_tado-0.18.14/PyTado/__init__.py +0 -0
  11. {python_tado-0.18.14 → python_tado-0.18.15}/AUTHORS +0 -0
  12. {python_tado-0.18.14 → python_tado-0.18.15}/LICENSE +0 -0
  13. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/__main__.py +0 -0
  14. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/const.py +0 -0
  15. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/exceptions.py +0 -0
  16. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/__init__.py +0 -0
  17. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/api/__init__.py +0 -0
  18. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/interface/api/hops_tado.py +0 -0
  19. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/logger.py +0 -0
  20. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/zone/__init__.py +0 -0
  21. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/zone/hops_zone.py +0 -0
  22. {python_tado-0.18.14 → python_tado-0.18.15}/PyTado/zone/my_zone.py +0 -0
  23. {python_tado-0.18.14 → python_tado-0.18.15}/README.md +0 -0
  24. {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/SOURCES.txt +0 -0
  25. {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/dependency_links.txt +0 -0
  26. {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/entry_points.txt +0 -0
  27. {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/not-zip-safe +0 -0
  28. {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/requires.txt +0 -0
  29. {python_tado-0.18.14 → python_tado-0.18.15}/python_tado.egg-info/top_level.txt +0 -0
  30. {python_tado-0.18.14 → python_tado-0.18.15}/setup.cfg +0 -0
  31. {python_tado-0.18.14 → python_tado-0.18.15}/tests/test_hops_zone.py +0 -0
  32. {python_tado-0.18.14 → python_tado-0.18.15}/tests/test_my_zone.py +0 -0
  33. {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.14
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
@@ -0,0 +1,6 @@
1
+ from importlib.metadata import PackageNotFoundError, version
2
+
3
+ try:
4
+ __version__ = version("python-tado")
5
+ except PackageNotFoundError:
6
+ __version__ = "test" # happens when running as pre-commit hook
@@ -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.14"
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.14
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