python-tado 0.19.2__tar.gz → 1.0.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.
Files changed (50) hide show
  1. {python_tado-0.19.2 → python_tado-1.0.0}/PKG-INFO +12 -23
  2. python_tado-1.0.0/PyTado/__init__.py +6 -0
  3. {python_tado-0.19.2 → python_tado-1.0.0}/PyTado/__main__.py +15 -9
  4. python_tado-1.0.0/PyTado/const.py +72 -0
  5. {python_tado-0.19.2 → python_tado-1.0.0}/PyTado/exceptions.py +4 -0
  6. python_tado-1.0.0/PyTado/factory/__init__.py +7 -0
  7. python_tado-1.0.0/PyTado/factory/initializer.py +90 -0
  8. {python_tado-0.19.2 → python_tado-1.0.0}/PyTado/http.py +210 -105
  9. {python_tado-0.19.2 → python_tado-1.0.0}/PyTado/interface/api/__init__.py +2 -1
  10. python_tado-1.0.0/PyTado/interface/api/base_tado.py +601 -0
  11. python_tado-1.0.0/PyTado/interface/api/hops_tado.py +418 -0
  12. python_tado-1.0.0/PyTado/interface/api/my_tado.py +363 -0
  13. python_tado-1.0.0/PyTado/interface/interface.py +161 -0
  14. {python_tado-0.19.2 → python_tado-1.0.0}/PyTado/logger.py +1 -1
  15. python_tado-1.0.0/PyTado/models/__init__.py +8 -0
  16. python_tado-1.0.0/PyTado/models/common/schedule.py +52 -0
  17. python_tado-1.0.0/PyTado/models/historic.py +137 -0
  18. python_tado-1.0.0/PyTado/models/home.py +206 -0
  19. python_tado-1.0.0/PyTado/models/line_x/__init__.py +14 -0
  20. python_tado-1.0.0/PyTado/models/line_x/device.py +62 -0
  21. python_tado-1.0.0/PyTado/models/line_x/installation.py +8 -0
  22. python_tado-1.0.0/PyTado/models/line_x/room.py +90 -0
  23. python_tado-1.0.0/PyTado/models/line_x/schedule.py +31 -0
  24. python_tado-1.0.0/PyTado/models/pre_line_x/__init__.py +23 -0
  25. python_tado-1.0.0/PyTado/models/pre_line_x/boiler.py +36 -0
  26. python_tado-1.0.0/PyTado/models/pre_line_x/device.py +42 -0
  27. python_tado-1.0.0/PyTado/models/pre_line_x/flow_temperature_optimization.py +34 -0
  28. python_tado-1.0.0/PyTado/models/pre_line_x/home.py +7 -0
  29. python_tado-1.0.0/PyTado/models/pre_line_x/schedule.py +17 -0
  30. python_tado-1.0.0/PyTado/models/pre_line_x/zone.py +288 -0
  31. python_tado-1.0.0/PyTado/models/return_models.py +28 -0
  32. python_tado-1.0.0/PyTado/models/util.py +93 -0
  33. python_tado-1.0.0/PyTado/types.py +207 -0
  34. python_tado-1.0.0/PyTado/zone/__init__.py +6 -0
  35. python_tado-1.0.0/PyTado/zone/base_zone.py +471 -0
  36. python_tado-1.0.0/PyTado/zone/hops_zone.py +360 -0
  37. python_tado-1.0.0/PyTado/zone/my_zone.py +506 -0
  38. {python_tado-0.19.2 → python_tado-1.0.0}/README.md +5 -20
  39. {python_tado-0.19.2 → python_tado-1.0.0}/pyproject.toml +20 -10
  40. python_tado-0.19.2/PyTado/const.py +0 -99
  41. python_tado-0.19.2/PyTado/interface/api/hops_tado.py +0 -376
  42. python_tado-0.19.2/PyTado/interface/api/my_tado.py +0 -623
  43. python_tado-0.19.2/PyTado/interface/interface.py +0 -365
  44. python_tado-0.19.2/PyTado/zone/__init__.py +0 -6
  45. python_tado-0.19.2/PyTado/zone/hops_zone.py +0 -132
  46. python_tado-0.19.2/PyTado/zone/my_zone.py +0 -215
  47. {python_tado-0.19.2 → python_tado-1.0.0}/AUTHORS +0 -0
  48. {python_tado-0.19.2 → python_tado-1.0.0}/LICENSE +0 -0
  49. {python_tado-0.19.2 → python_tado-1.0.0}/PyTado/interface/__init__.py +0 -0
  50. {python_tado-0.19.2/PyTado → python_tado-1.0.0/PyTado/models/common}/__init__.py +0 -0
@@ -1,8 +1,10 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: python-tado
3
- Version: 0.19.2
3
+ Version: 1.0.0
4
4
  Summary: PyTado from chrism0dwk, modified by w.malgadey, diplix, michaelarnauts, LenhartStephan, splifter, syssi, andersonshatch, Yippy, p0thi, Coffee2CodeNL, chiefdragon, FilBr, nikilase, albertomontesg, Moritz-Schmidt, palazzem
5
5
  License: GPL-3.0-or-later
6
+ License-File: AUTHORS
7
+ License-File: LICENSE
6
8
  Keywords: tado
7
9
  Author: Chris Jewell
8
10
  Author-email: chrism0dwk@gmail.com
@@ -16,13 +18,15 @@ Classifier: Programming Language :: Python :: 3
16
18
  Classifier: Programming Language :: Python :: 3.11
17
19
  Classifier: Programming Language :: Python :: 3.12
18
20
  Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
19
22
  Classifier: Topic :: Home Automation
20
23
  Provides-Extra: all
21
24
  Provides-Extra: dev
22
25
  Provides-Extra: lint
23
26
  Provides-Extra: test
24
- Requires-Dist: black (>=24.10) ; extra == "lint" or extra == "all"
25
27
  Requires-Dist: pre-commit ; extra == "dev" or extra == "all"
28
+ Requires-Dist: pydantic (>=2.10.6,<3.0.0)
29
+ Requires-Dist: pydoc-markdown
26
30
  Requires-Dist: pylint ; extra == "lint" or extra == "all"
27
31
  Requires-Dist: pytest ; extra == "test" or extra == "all"
28
32
  Requires-Dist: pytest-cov ; extra == "test" or extra == "all"
@@ -49,14 +53,14 @@ PyTado is a Python module implementing an interface to the Tado web API. It allo
49
53
  Tado heating system for the purposes of monitoring or controlling their heating system, beyond what Tado themselves
50
54
  currently offer.
51
55
 
52
- It is hoped that this module might be used by those who wish to tweak their Tado systems, and further optimise their
56
+ It is hoped that this module might be used by those who wish to tweak their Tado systems, and further optimize their
53
57
  heating setups.
54
58
 
55
59
  ---
56
60
 
57
61
  Original author: Chris Jewell <chrism0dwk@gmail.com>
58
62
 
59
- Licence: GPL v3
63
+ License: GPL v3
60
64
 
61
65
  Copyright: Chris Jewell 2016-2018
62
66
 
@@ -65,7 +69,7 @@ Copyright: Chris Jewell 2016-2018
65
69
  Besides owning a Tado system, I have no connection with the Tado company themselves. PyTado was created for my own use,
66
70
  and for others who may wish to experiment with personal Internet of Things systems. I receive no help (financial or
67
71
  otherwise) from Tado, and have no business interest with them. This software is provided without warranty, according to
68
- the GNU Public Licence version 3, and should therefore not be used where it may endanger life, financial stakes, or
72
+ the GNU Public License version 3, and should therefore not be used where it may endanger life, financial stakes, or
69
73
  cause discomfort and inconvenience to others.
70
74
 
71
75
  ## Usage
@@ -93,7 +97,7 @@ It is possible to save the refresh token and reuse to skip the next login.
93
97
 
94
98
  The following code will use the `refresh_token` file to save the refresh-token after login, and load the refresh-token if you create the Tado interface class again.
95
99
 
96
- If the file doesn't exists, the webbrowser is started and the device authentication url is automatically opened. You can activate the device in the browser. When you restart the program, the refresh-token is reused and no webbrowser will be opened.
100
+ If the file doesn't exists, the web browser is started and the device authentication url is automatically opened. You can activate the device in the browser. When you restart the program, the refresh-token is reused and no web browser will be opened.
97
101
 
98
102
  ```python
99
103
  import webbrowser # only needed for direct web browser access
@@ -150,7 +154,6 @@ if __name__ == "__main__":
150
154
  Note: For developers, there is an `example.py` script in `examples/` which is configured to fetch data from your account.
151
155
  You can then invoke `python examples/example.py`.
152
156
 
153
-
154
157
  ## Contributing
155
158
 
156
159
  We are very open to the community's contributions - be it a quick fix of a typo, or a completely new feature!
@@ -182,20 +185,7 @@ git clone https://github.com/yourusername/PyTado.git
182
185
  cd PyTado
183
186
  ```
184
187
 
185
- Then, to create your development environment and install the project with its dependencies, execute the following
186
- commands in your terminal:
187
-
188
- ```bash
189
- # Create and activate a new virtual environment
190
- python3 -m venv venv
191
- source venv/bin/activate
192
-
193
- # install all dependencies
194
- poetry install
195
-
196
- # Install pre-commit hooks
197
- poetry run pre-commit install
198
- ```
188
+ Then, to create your development environment and install the project with its dependencies, execute the `./scripts/bootstrap` script.
199
189
 
200
190
  ### Coding Guidelines
201
191
 
@@ -234,7 +224,6 @@ A message from the original author:
234
224
  >
235
225
  > Chris Jewell
236
226
 
237
-
238
227
  [devcontainer-shield]: https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode
239
228
  [devcontainer]: https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/wmalgadey/PyTado
240
229
 
@@ -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
@@ -9,7 +9,7 @@ import sys
9
9
  from PyTado.interface import Tado
10
10
 
11
11
 
12
- def log_in(args):
12
+ def log_in(args: argparse.Namespace) -> Tado:
13
13
  """
14
14
  Log in to the Tado API by activating the current device.
15
15
 
@@ -27,7 +27,7 @@ def log_in(args):
27
27
  return t
28
28
 
29
29
 
30
- def get_me(args):
30
+ def get_me(args: argparse.Namespace) -> None:
31
31
  """
32
32
  Retrieve and print home information from the Tado API.
33
33
 
@@ -39,7 +39,7 @@ def get_me(args):
39
39
  print(me)
40
40
 
41
41
 
42
- def get_state(args):
42
+ def get_state(args: argparse.Namespace) -> None:
43
43
  """
44
44
  Retrieve and print the state of a specific zone from the Tado API.
45
45
 
@@ -51,7 +51,7 @@ def get_state(args):
51
51
  print(zone)
52
52
 
53
53
 
54
- def get_states(args):
54
+ def get_states(args: argparse.Namespace) -> None:
55
55
  """
56
56
  Retrieve and print the states of all zones from the Tado API.
57
57
 
@@ -63,7 +63,7 @@ def get_states(args):
63
63
  print(zones)
64
64
 
65
65
 
66
- def get_capabilities(args):
66
+ def get_capabilities(args: argparse.Namespace) -> None:
67
67
  """
68
68
  Retrieve and print the capabilities of a specific zone from the Tado API.
69
69
 
@@ -75,7 +75,7 @@ def get_capabilities(args):
75
75
  print(capabilities)
76
76
 
77
77
 
78
- def main():
78
+ def main() -> None:
79
79
  """
80
80
  Main method for the script.
81
81
 
@@ -109,17 +109,23 @@ def main():
109
109
  show_config_parser = subparsers.add_parser("get_me", help="Get home information.")
110
110
  show_config_parser.set_defaults(func=get_me)
111
111
 
112
- start_activity_parser = subparsers.add_parser("get_state", help="Get state of zone.")
112
+ start_activity_parser = subparsers.add_parser(
113
+ "get_state", help="Get state of zone."
114
+ )
113
115
  start_activity_parser.add_argument("--zone", help="Zone to get the state of.")
114
116
  start_activity_parser.set_defaults(func=get_state)
115
117
 
116
- start_activity_parser = subparsers.add_parser("get_states", help="Get states of all zones.")
118
+ start_activity_parser = subparsers.add_parser(
119
+ "get_states", help="Get states of all zones."
120
+ )
117
121
  start_activity_parser.set_defaults(func=get_states)
118
122
 
119
123
  start_activity_parser = subparsers.add_parser(
120
124
  "get_capabilities", help="Get capabilities of zone."
121
125
  )
122
- start_activity_parser.add_argument("--zone", help="Zone to get the capabilities of.")
126
+ start_activity_parser.add_argument(
127
+ "--zone", help="Zone to get the capabilities of."
128
+ )
123
129
  start_activity_parser.set_defaults(func=get_capabilities)
124
130
 
125
131
  args = parser.parse_args()
@@ -0,0 +1,72 @@
1
+ """Constant values for the Tado component."""
2
+
3
+ from PyTado.types import FanLevel, FanSpeed, HvacAction, HvacMode
4
+
5
+ # API client ID
6
+ CLIENT_ID_DEVICE = "1bb50063-6b0c-4d11-bd99-387f4a91cc46" # nosec B105
7
+
8
+
9
+ CONST_LINK_OFFLINE = "OFFLINE"
10
+ CONST_CONNECTION_OFFLINE = "OFFLINE"
11
+
12
+
13
+ FAN_SPEED_TO_FAN_LEVEL = {
14
+ FanSpeed.OFF: FanLevel.OFF,
15
+ FanSpeed.AUTO: FanLevel.AUTO,
16
+ FanSpeed.LOW: FanLevel.LEVEL1,
17
+ FanSpeed.MIDDLE: FanLevel.LEVEL2,
18
+ FanSpeed.HIGH: FanLevel.LEVEL3,
19
+ }
20
+
21
+ # When we change the temperature setting, we need an overlay mode
22
+ CONST_OVERLAY_TADO_MODE = (
23
+ "NEXT_TIME_BLOCK" # wait until tado changes the mode automatic
24
+ )
25
+ CONST_OVERLAY_MANUAL = "MANUAL" # the user has changed the temperature or mode manually
26
+ CONST_OVERLAY_TIMER = "TIMER" # the temperature will be reset after a timespan
27
+
28
+ # Heat always comes first since we get the
29
+ # min and max tempatures for the zone from
30
+ # it.
31
+ # Heat is preferred as it generally has a lower minimum temperature
32
+ ORDERED_KNOWN_TADO_MODES = [
33
+ HvacMode.HEAT,
34
+ HvacMode.COOL,
35
+ HvacMode.AUTO,
36
+ HvacMode.DRY,
37
+ HvacMode.FAN,
38
+ ]
39
+
40
+ TADO_MODES_TO_HVAC_ACTION: dict[HvacMode, HvacAction] = {
41
+ HvacMode.HEAT: HvacAction.HEATING,
42
+ HvacMode.DRY: HvacAction.DRYING,
43
+ HvacMode.FAN: HvacAction.FAN,
44
+ HvacMode.COOL: HvacAction.COOLING,
45
+ }
46
+
47
+ TADO_HVAC_ACTION_TO_MODES: dict[HvacAction, HvacMode | HvacAction] = {
48
+ HvacAction.HEATING: HvacMode.HEAT,
49
+ HvacAction.HOT_WATER: HvacAction.HEATING,
50
+ HvacAction.DRYING: HvacMode.DRY,
51
+ HvacAction.FAN: HvacMode.FAN,
52
+ HvacAction.COOLING: HvacMode.COOL,
53
+ }
54
+
55
+ # These modes will not allow a temp to be set
56
+ TADO_MODES_WITH_NO_TEMP_SETTING = [
57
+ HvacMode.AUTO,
58
+ HvacMode.DRY,
59
+ HvacMode.FAN,
60
+ ]
61
+
62
+ DEFAULT_TADO_PRECISION = 0.1
63
+ DEFAULT_TADOX_PRECISION = 0.01
64
+ DEFAULT_DATE_FORMAT = "%Y-%m-%d"
65
+
66
+ DEFAULT_TADOX_MIN_TEMP = 5.0
67
+ DEFAULT_TADOX_MAX_TEMP = 30.0
68
+
69
+ HOME_DOMAIN = "homes"
70
+ DEVICE_DOMAIN = "devices"
71
+
72
+ HTTP_CODES_OK = [200, 201, 202, 204]
@@ -19,3 +19,7 @@ class TadoNoCredentialsException(TadoCredentialsException):
19
19
 
20
20
  class TadoWrongCredentialsException(TadoCredentialsException):
21
21
  """Exception to indicate wrong credentials"""
22
+
23
+
24
+ class TadoRateLimitException(TadoException):
25
+ """Exception to indicate API rate limit has been exceeded."""
@@ -0,0 +1,7 @@
1
+ """Factory method for easy initialization."""
2
+
3
+ from ..interface.api.hops_tado import TadoX
4
+ from ..interface.api.my_tado import Tado
5
+ from .initializer import TadoClientInitializer
6
+
7
+ __all__ = ["Tado", "TadoX", "TadoClientInitializer"]
@@ -0,0 +1,90 @@
1
+ """
2
+ PyTado API factory to use app.tado.com or hops.tado.com
3
+ """
4
+
5
+ from typing import Self
6
+
7
+ import requests
8
+
9
+ import PyTado.interface.api as API
10
+ from PyTado.exceptions import TadoException
11
+ from PyTado.http import DeviceActivationStatus, Http
12
+
13
+
14
+ class TadoClientInitializer:
15
+ """Class to authenticate and get the Tado client."""
16
+
17
+ http: Http
18
+ debug: bool = False
19
+ token_file_path: str | None = None
20
+ saved_refresh_token: str | None = None
21
+ http_session: requests.Session | None = None
22
+
23
+ def __init__(
24
+ self,
25
+ token_file_path: str | None = None,
26
+ saved_refresh_token: str | None = None,
27
+ http_session: requests.Session | None = None,
28
+ debug: bool = False,
29
+ ):
30
+ self.token_file_path = token_file_path
31
+ self.saved_refresh_token = saved_refresh_token
32
+ self.http_session = http_session
33
+ self.debug = debug
34
+ self.http = Http(
35
+ token_file_path=token_file_path,
36
+ saved_refresh_token=saved_refresh_token,
37
+ http_session=http_session,
38
+ debug=debug,
39
+ )
40
+
41
+ def get_verification_url(self) -> str | None:
42
+ """Returns the URL for device verification."""
43
+ if self.http.device_activation_status == DeviceActivationStatus.NOT_STARTED:
44
+ self.device_activation()
45
+
46
+ return self.http.device_verification_url
47
+
48
+ def device_activation(self) -> Self:
49
+ """Activates the device.
50
+
51
+ Caution: this method will block until the device is activated or the timeout is reached.
52
+ """
53
+ self.http.device_activation()
54
+
55
+ return self
56
+
57
+ def get_client(self) -> API.TadoX | API.Tado:
58
+ """Returns the client instance after device activation."""
59
+ if self.http.device_activation_status == DeviceActivationStatus.COMPLETED:
60
+ if self.http.is_x_line:
61
+ return API.TadoX.from_http(http=self.http, debug=self.debug)
62
+
63
+ return API.Tado.from_http(http=self.http, debug=self.debug)
64
+
65
+ raise TadoException(
66
+ "Authentication failed. Please check the device verification URL and try again."
67
+ )
68
+
69
+ def authenticate_and_get_client(self) -> API.TadoX | API.Tado:
70
+ """Authenticate and get the client instance, prompting for device activation if needed."""
71
+ print("Starting device activation process...")
72
+ print("Device activation status: ", self.http.device_activation_status)
73
+
74
+ if self.http.device_activation_status != DeviceActivationStatus.COMPLETED:
75
+ print("Click on the link to log in to your Tado account.")
76
+ print("Device verification URL: ", self.get_verification_url())
77
+
78
+ self.device_activation()
79
+
80
+ if (
81
+ self.http.device_activation_status == DeviceActivationStatus.COMPLETED
82
+ ): # pyright: ignore[reportUnnecessaryComparison]
83
+ print("Device activation completed successfully.")
84
+ else:
85
+ raise TadoException(
86
+ "Device activation failed. "
87
+ "Please check the device verification URL and try again."
88
+ )
89
+
90
+ return self.get_client()