vi-api-client 6.1.1__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 (39) hide show
  1. vi_api_client-6.1.1/LICENSE +21 -0
  2. vi_api_client-6.1.1/MANIFEST.in +17 -0
  3. vi_api_client-6.1.1/PKG-INFO +264 -0
  4. vi_api_client-6.1.1/README.md +228 -0
  5. vi_api_client-6.1.1/pyproject.toml +111 -0
  6. vi_api_client-6.1.1/setup.cfg +4 -0
  7. vi_api_client-6.1.1/src/vi_api_client/__init__.py +74 -0
  8. vi_api_client-6.1.1/src/vi_api_client/_adapter.py +321 -0
  9. vi_api_client-6.1.1/src/vi_api_client/_feature_diff.py +250 -0
  10. vi_api_client-6.1.1/src/vi_api_client/_types.py +12 -0
  11. vi_api_client-6.1.1/src/vi_api_client/auth.py +365 -0
  12. vi_api_client-6.1.1/src/vi_api_client/cli.py +1368 -0
  13. vi_api_client-6.1.1/src/vi_api_client/client.py +1004 -0
  14. vi_api_client-6.1.1/src/vi_api_client/const.py +20 -0
  15. vi_api_client-6.1.1/src/vi_api_client/credentials.py +136 -0
  16. vi_api_client-6.1.1/src/vi_api_client/exceptions.py +112 -0
  17. vi_api_client-6.1.1/src/vi_api_client/fixture_client.py +169 -0
  18. vi_api_client-6.1.1/src/vi_api_client/fixtures/Vitocal200S.json +3968 -0
  19. vi_api_client-6.1.1/src/vi_api_client/fixtures/Vitocal222S.json +6258 -0
  20. vi_api_client-6.1.1/src/vi_api_client/fixtures/Vitocal250A.json +6909 -0
  21. vi_api_client-6.1.1/src/vi_api_client/fixtures/Vitocal333G-with-Vitovent300F.json +4833 -0
  22. vi_api_client-6.1.1/src/vi_api_client/fixtures/Vitocharge03.json +896 -0
  23. vi_api_client-6.1.1/src/vi_api_client/fixtures/Vitodens200W.json +4640 -0
  24. vi_api_client-6.1.1/src/vi_api_client/fixtures/Vitopure350.json +1087 -0
  25. vi_api_client-6.1.1/src/vi_api_client/fixtures/discovery.json +62 -0
  26. vi_api_client-6.1.1/src/vi_api_client/fixtures/event_history.json +44 -0
  27. vi_api_client-6.1.1/src/vi_api_client/fixtures/event_history_final_page.json +6 -0
  28. vi_api_client-6.1.1/src/vi_api_client/models.py +536 -0
  29. vi_api_client-6.1.1/src/vi_api_client/parsing.py +592 -0
  30. vi_api_client-6.1.1/src/vi_api_client/privacy.py +172 -0
  31. vi_api_client-6.1.1/src/vi_api_client/py.typed +1 -0
  32. vi_api_client-6.1.1/src/vi_api_client/utils.py +138 -0
  33. vi_api_client-6.1.1/src/vi_api_client/validation.py +52 -0
  34. vi_api_client-6.1.1/src/vi_api_client.egg-info/PKG-INFO +264 -0
  35. vi_api_client-6.1.1/src/vi_api_client.egg-info/SOURCES.txt +37 -0
  36. vi_api_client-6.1.1/src/vi_api_client.egg-info/dependency_links.txt +1 -0
  37. vi_api_client-6.1.1/src/vi_api_client.egg-info/entry_points.txt +2 -0
  38. vi_api_client-6.1.1/src/vi_api_client.egg-info/requires.txt +11 -0
  39. vi_api_client-6.1.1/src/vi_api_client.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Michael
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,17 @@
1
+ include LICENSE
2
+ include README.md
3
+ include pyproject.toml
4
+
5
+
6
+ recursive-include src/vi_api_client *.py
7
+ include src/vi_api_client/py.typed
8
+ recursive-include src/vi_api_client/fixtures *.json
9
+
10
+ # Exclude documentation and local config
11
+ exclude tokens.json
12
+ exclude HA_INTEGRATION_HANDOVER.md
13
+ prune tests
14
+ prune docs
15
+ global-exclude .DS_Store
16
+ global-exclude *.pyc
17
+ global-exclude __pycache__
@@ -0,0 +1,264 @@
1
+ Metadata-Version: 2.4
2
+ Name: vi_api_client
3
+ Version: 6.1.1
4
+ Summary: Async Python client for Viessmann Climate Solutions API
5
+ Author: Michael
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/ignazhabibi/vi_api_client
8
+ Project-URL: Documentation, https://github.com/ignazhabibi/vi_api_client/tree/main/docs
9
+ Project-URL: Issues, https://github.com/ignazhabibi/vi_api_client/issues
10
+ Project-URL: Changelog, https://github.com/ignazhabibi/vi_api_client/releases
11
+ Keywords: api-client,asyncio,heat-pump,heating,home-assistant,viessmann
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Framework :: AsyncIO
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Programming Language :: Python :: 3.15
20
+ Classifier: Topic :: Home Automation
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.14
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: aiohttp>=3.13.3
26
+ Provides-Extra: dev
27
+ Requires-Dist: aiointercept>=0.1.12; extra == "dev"
28
+ Requires-Dist: build>=1.4; extra == "dev"
29
+ Requires-Dist: pytest>=9; extra == "dev"
30
+ Requires-Dist: pytest-asyncio>=1.3; extra == "dev"
31
+ Requires-Dist: pytest-cov>=7.1; extra == "dev"
32
+ Requires-Dist: pyright==1.1.414; extra == "dev"
33
+ Requires-Dist: pre-commit==4.7.0; extra == "dev"
34
+ Requires-Dist: ruff==0.17.4; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # Viessmann API Python Client
38
+
39
+ A Python library for accessing the [Viessmann Climate Solutions API](https://developer.viessmann-climatesolutions.com/start.html).
40
+ Designed for integration with Home Assistant and other async Python applications.
41
+
42
+ ## Features
43
+
44
+ - **Asynchronous**: Built on `aiohttp` and `asyncio`.
45
+ - **OAuth2 Authentication**: Handles token retrieval and automatic renewal.
46
+ - **Auto-Discovery**: Automatically finds installations, gateways, and devices.
47
+ - **Recursive Feature Flattening**: Converts complex nested API responses into a simple, flat list of features (e.g., `heating.circuits.0.heating.curve.shift`).
48
+ - **Gateway-Scoped Refresh**: Refreshes multiple known devices with one normal-case request while preserving partial successes.
49
+ - **Command Execution**: Supports safe single-feature writes with automatic
50
+ parameter resolution and explicit multi-parameter commands.
51
+ - **Fixture-backed Client**: Runs the same client workflows against bundled real-device
52
+ responses without authentication, sessions, or network requests.
53
+ - **Strictly Typed**: Ships as a PEP 561 complete package with `py.typed`; the
54
+ shipped code passes strict Pyright and dynamic values follow a typed JSON
55
+ value contract.
56
+
57
+ ## Public API
58
+
59
+ Import consumer-facing symbols from `vi_api_client`:
60
+
61
+ ```python
62
+ from vi_api_client import (
63
+ AbstractAuth,
64
+ CommandResponse,
65
+ DEFAULT_SCOPES,
66
+ Device,
67
+ ENDPOINT_AUTHORIZE,
68
+ ENDPOINT_TOKEN,
69
+ EventHistoryPage,
70
+ Feature,
71
+ FeatureControl,
72
+ FeatureValue,
73
+ Gateway,
74
+ GatewayDeviceRefreshResult,
75
+ Installation,
76
+ InstallationEvent,
77
+ JsonValue,
78
+ FixtureViClient,
79
+ OAuth,
80
+ ScheduleConstraints,
81
+ ValidationDetail,
82
+ ViAuthError,
83
+ ViClient,
84
+ ViConnectionError,
85
+ ViError,
86
+ ViNotFoundError,
87
+ ViRateLimitError,
88
+ ViResponseError,
89
+ ViServerInternalError,
90
+ ViValidationError,
91
+ format_feature,
92
+ redact_device,
93
+ redact_feature,
94
+ redact_sensitive,
95
+ validate_json_value,
96
+ )
97
+ ```
98
+
99
+ `DEFAULT_SCOPES`, `ENDPOINT_AUTHORIZE`, and `ENDPOINT_TOKEN` support external
100
+ OAuth integrations. `JsonValue`, `FeatureValue`, `ValidationDetail`, and
101
+ `validate_json_value` form the public recursive JSON value contract that
102
+ dynamic feature values and API validation details follow. `redact_sensitive`,
103
+ `redact_feature`, and `redact_device` redact secrets, address data,
104
+ identifiers, and coordinates in log text, API documents, and model objects.
105
+ CLI helpers, transport details, persistence, and parsing remain available from
106
+ their dedicated modules.
107
+
108
+ ## Installation
109
+
110
+ **Requires Python 3.14+.** Install the released package from PyPI:
111
+
112
+ ```bash
113
+ python3.14 -m venv .venv
114
+ source .venv/bin/activate
115
+ pip install vi_api_client
116
+ ```
117
+
118
+ To work on the library itself, install it from a clone in editable mode:
119
+
120
+ ```bash
121
+ git clone https://github.com/ignazhabibi/vi_api_client.git
122
+ cd vi_api_client
123
+ pip install -e .
124
+ ```
125
+
126
+ ## Development and Tests
127
+
128
+ Install the development dependencies with the CI constraints to reproduce the
129
+ tested HTTP client and mock combination locally:
130
+
131
+ ```bash
132
+ python -m pip install -c constraints-ci.txt '.[dev]'
133
+ pre-commit install
134
+ ruff check .
135
+ ruff format --check .
136
+ pyright --pythonpath python
137
+ pyright --project pyrightconfig.strict.json
138
+ python -m pytest -q
139
+ python scripts/check_coverage.py
140
+ python -m build
141
+ python scripts/verify_distributions.py
142
+ ```
143
+
144
+ The shipped package is strictly typed and PEP 561 complete: the strict
145
+ Pyright pass covers `src/vi_api_client`, the built wheel and source
146
+ distribution ship `py.typed`, and the installed wheel passes
147
+ `pyright --verifytypes vi_api_client --ignoreexternal`. Tests remain under
148
+ standard type checking. The suite must keep at least 95% line
149
+ and branch coverage over `src/vi_api_client`; `scripts/check_coverage.py`
150
+ enforces both thresholds in the quality gate.
151
+
152
+ ## Quick Start
153
+
154
+ ### CLI
155
+
156
+ The `vi-client` tool is the easiest way to explore the API.
157
+
158
+ ```bash
159
+ # 1. Login
160
+ vi-client login --client-id <YOUR_CLIENT_ID>
161
+
162
+ # 2. List Devices
163
+ vi-client list-devices
164
+
165
+ # 3. List only enabled Features with values (auto-detects first device)
166
+ vi-client list-features --enabled --values
167
+
168
+ # 4. List Writable Features (Settings)
169
+ vi-client list-writable
170
+
171
+ # 5. List the complete installation event history (last 7 days)
172
+ vi-client list-events --days 7
173
+ ```
174
+
175
+ See [CLI Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/06_cli_reference.md) for more details.
176
+
177
+ ### Python Code
178
+
179
+ The example reads tokens from `tokens.json`. Create that file once with
180
+ `vi-client login`, or log in from Python as shown in the
181
+ [Authentication reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/03_auth_reference.md#first-login).
182
+
183
+ ```python
184
+ import asyncio
185
+ import aiohttp
186
+ from vi_api_client import OAuth, ViClient
187
+
188
+
189
+ async def main():
190
+ async with aiohttp.ClientSession() as session:
191
+ # Initialize Auth (tokens saved to tokens.json)
192
+ auth = OAuth(
193
+ client_id="YOUR_CLIENT_ID",
194
+ redirect_uri="http://localhost:4200/",
195
+ token_file="tokens.json",
196
+ websession=session,
197
+ )
198
+
199
+ client = ViClient(auth)
200
+
201
+ # 1. Get Installations & Gateways
202
+ installations = await client.get_installations()
203
+ if not installations:
204
+ return
205
+ installation = installations[0]
206
+
207
+ gateways = await client.get_gateways()
208
+ gateway = next(
209
+ (
210
+ gateway
211
+ for gateway in gateways
212
+ if gateway.installation_id == installation.id
213
+ ),
214
+ None,
215
+ )
216
+ if gateway is None:
217
+ return
218
+
219
+ # 2. Discover and refresh devices behind one gateway
220
+ devices = await client.get_devices(installation.id, gateway.serial)
221
+ refresh = await client.refresh_gateway_devices(devices)
222
+ for device_id, error in refresh.errors_by_device_id.items():
223
+ print(f"Device {device_id} could not be refreshed: {error}")
224
+ if not refresh.updated_devices:
225
+ return
226
+ device = refresh.updated_devices[0]
227
+ print(f"Device: {device.model_id} ({device.status})")
228
+
229
+ # 3. Iterate Features (Flat List)
230
+ for feature in device.features:
231
+ print(f"{feature.name}: {feature.value}")
232
+
233
+ # 4. Write one Feature with automatic dependency resolution
234
+ # Find a writable feature (e.g. heating curve slope)
235
+ slope = next(
236
+ (f for f in device.features if "curve.slope" in f.name and f.is_writable),
237
+ None,
238
+ )
239
+ if slope:
240
+ print(f"Setting slope to 1.4...")
241
+ response, device = await client.set_feature(device, slope, 1.4)
242
+ if response.success:
243
+ print("✅ Success! Device updated.")
244
+ # Use updated device for subsequent calls
245
+
246
+
247
+ if __name__ == "__main__":
248
+ asyncio.run(main())
249
+ ```
250
+
251
+ ## Documentation
252
+
253
+ The detailed documentation is available in the `docs/` directory:
254
+
255
+ 1. **[Getting Started](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/01_getting_started.md)**: Installation and First Steps.
256
+ 2. **[API Structure & Concepts](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/02_api_structure.md)**: Understanding the Flat Architecture.
257
+ 3. **[Authentication & Connection](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/03_auth_reference.md)**: Tokens, Sessions, and Thread-Safety.
258
+ 4. **[Models Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/04_models_reference.md)**: Devices, Features, and Controls.
259
+ 5. **[Client Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/05_client_reference.md)**: The `ViClient` class methods.
260
+ 6. **[CLI Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/06_cli_reference.md)**: Using the command line interface.
261
+ 7. **[Exceptions Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/07_exceptions_reference.md)**: Handling errors.
262
+ 8. **[Architecture Guide](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/08_architecture.md)**: System structure,
263
+ responsibilities, data flows, and diagrams explained for developers and
264
+ non-specialists.
@@ -0,0 +1,228 @@
1
+ # Viessmann API Python Client
2
+
3
+ A Python library for accessing the [Viessmann Climate Solutions API](https://developer.viessmann-climatesolutions.com/start.html).
4
+ Designed for integration with Home Assistant and other async Python applications.
5
+
6
+ ## Features
7
+
8
+ - **Asynchronous**: Built on `aiohttp` and `asyncio`.
9
+ - **OAuth2 Authentication**: Handles token retrieval and automatic renewal.
10
+ - **Auto-Discovery**: Automatically finds installations, gateways, and devices.
11
+ - **Recursive Feature Flattening**: Converts complex nested API responses into a simple, flat list of features (e.g., `heating.circuits.0.heating.curve.shift`).
12
+ - **Gateway-Scoped Refresh**: Refreshes multiple known devices with one normal-case request while preserving partial successes.
13
+ - **Command Execution**: Supports safe single-feature writes with automatic
14
+ parameter resolution and explicit multi-parameter commands.
15
+ - **Fixture-backed Client**: Runs the same client workflows against bundled real-device
16
+ responses without authentication, sessions, or network requests.
17
+ - **Strictly Typed**: Ships as a PEP 561 complete package with `py.typed`; the
18
+ shipped code passes strict Pyright and dynamic values follow a typed JSON
19
+ value contract.
20
+
21
+ ## Public API
22
+
23
+ Import consumer-facing symbols from `vi_api_client`:
24
+
25
+ ```python
26
+ from vi_api_client import (
27
+ AbstractAuth,
28
+ CommandResponse,
29
+ DEFAULT_SCOPES,
30
+ Device,
31
+ ENDPOINT_AUTHORIZE,
32
+ ENDPOINT_TOKEN,
33
+ EventHistoryPage,
34
+ Feature,
35
+ FeatureControl,
36
+ FeatureValue,
37
+ Gateway,
38
+ GatewayDeviceRefreshResult,
39
+ Installation,
40
+ InstallationEvent,
41
+ JsonValue,
42
+ FixtureViClient,
43
+ OAuth,
44
+ ScheduleConstraints,
45
+ ValidationDetail,
46
+ ViAuthError,
47
+ ViClient,
48
+ ViConnectionError,
49
+ ViError,
50
+ ViNotFoundError,
51
+ ViRateLimitError,
52
+ ViResponseError,
53
+ ViServerInternalError,
54
+ ViValidationError,
55
+ format_feature,
56
+ redact_device,
57
+ redact_feature,
58
+ redact_sensitive,
59
+ validate_json_value,
60
+ )
61
+ ```
62
+
63
+ `DEFAULT_SCOPES`, `ENDPOINT_AUTHORIZE`, and `ENDPOINT_TOKEN` support external
64
+ OAuth integrations. `JsonValue`, `FeatureValue`, `ValidationDetail`, and
65
+ `validate_json_value` form the public recursive JSON value contract that
66
+ dynamic feature values and API validation details follow. `redact_sensitive`,
67
+ `redact_feature`, and `redact_device` redact secrets, address data,
68
+ identifiers, and coordinates in log text, API documents, and model objects.
69
+ CLI helpers, transport details, persistence, and parsing remain available from
70
+ their dedicated modules.
71
+
72
+ ## Installation
73
+
74
+ **Requires Python 3.14+.** Install the released package from PyPI:
75
+
76
+ ```bash
77
+ python3.14 -m venv .venv
78
+ source .venv/bin/activate
79
+ pip install vi_api_client
80
+ ```
81
+
82
+ To work on the library itself, install it from a clone in editable mode:
83
+
84
+ ```bash
85
+ git clone https://github.com/ignazhabibi/vi_api_client.git
86
+ cd vi_api_client
87
+ pip install -e .
88
+ ```
89
+
90
+ ## Development and Tests
91
+
92
+ Install the development dependencies with the CI constraints to reproduce the
93
+ tested HTTP client and mock combination locally:
94
+
95
+ ```bash
96
+ python -m pip install -c constraints-ci.txt '.[dev]'
97
+ pre-commit install
98
+ ruff check .
99
+ ruff format --check .
100
+ pyright --pythonpath python
101
+ pyright --project pyrightconfig.strict.json
102
+ python -m pytest -q
103
+ python scripts/check_coverage.py
104
+ python -m build
105
+ python scripts/verify_distributions.py
106
+ ```
107
+
108
+ The shipped package is strictly typed and PEP 561 complete: the strict
109
+ Pyright pass covers `src/vi_api_client`, the built wheel and source
110
+ distribution ship `py.typed`, and the installed wheel passes
111
+ `pyright --verifytypes vi_api_client --ignoreexternal`. Tests remain under
112
+ standard type checking. The suite must keep at least 95% line
113
+ and branch coverage over `src/vi_api_client`; `scripts/check_coverage.py`
114
+ enforces both thresholds in the quality gate.
115
+
116
+ ## Quick Start
117
+
118
+ ### CLI
119
+
120
+ The `vi-client` tool is the easiest way to explore the API.
121
+
122
+ ```bash
123
+ # 1. Login
124
+ vi-client login --client-id <YOUR_CLIENT_ID>
125
+
126
+ # 2. List Devices
127
+ vi-client list-devices
128
+
129
+ # 3. List only enabled Features with values (auto-detects first device)
130
+ vi-client list-features --enabled --values
131
+
132
+ # 4. List Writable Features (Settings)
133
+ vi-client list-writable
134
+
135
+ # 5. List the complete installation event history (last 7 days)
136
+ vi-client list-events --days 7
137
+ ```
138
+
139
+ See [CLI Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/06_cli_reference.md) for more details.
140
+
141
+ ### Python Code
142
+
143
+ The example reads tokens from `tokens.json`. Create that file once with
144
+ `vi-client login`, or log in from Python as shown in the
145
+ [Authentication reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/03_auth_reference.md#first-login).
146
+
147
+ ```python
148
+ import asyncio
149
+ import aiohttp
150
+ from vi_api_client import OAuth, ViClient
151
+
152
+
153
+ async def main():
154
+ async with aiohttp.ClientSession() as session:
155
+ # Initialize Auth (tokens saved to tokens.json)
156
+ auth = OAuth(
157
+ client_id="YOUR_CLIENT_ID",
158
+ redirect_uri="http://localhost:4200/",
159
+ token_file="tokens.json",
160
+ websession=session,
161
+ )
162
+
163
+ client = ViClient(auth)
164
+
165
+ # 1. Get Installations & Gateways
166
+ installations = await client.get_installations()
167
+ if not installations:
168
+ return
169
+ installation = installations[0]
170
+
171
+ gateways = await client.get_gateways()
172
+ gateway = next(
173
+ (
174
+ gateway
175
+ for gateway in gateways
176
+ if gateway.installation_id == installation.id
177
+ ),
178
+ None,
179
+ )
180
+ if gateway is None:
181
+ return
182
+
183
+ # 2. Discover and refresh devices behind one gateway
184
+ devices = await client.get_devices(installation.id, gateway.serial)
185
+ refresh = await client.refresh_gateway_devices(devices)
186
+ for device_id, error in refresh.errors_by_device_id.items():
187
+ print(f"Device {device_id} could not be refreshed: {error}")
188
+ if not refresh.updated_devices:
189
+ return
190
+ device = refresh.updated_devices[0]
191
+ print(f"Device: {device.model_id} ({device.status})")
192
+
193
+ # 3. Iterate Features (Flat List)
194
+ for feature in device.features:
195
+ print(f"{feature.name}: {feature.value}")
196
+
197
+ # 4. Write one Feature with automatic dependency resolution
198
+ # Find a writable feature (e.g. heating curve slope)
199
+ slope = next(
200
+ (f for f in device.features if "curve.slope" in f.name and f.is_writable),
201
+ None,
202
+ )
203
+ if slope:
204
+ print(f"Setting slope to 1.4...")
205
+ response, device = await client.set_feature(device, slope, 1.4)
206
+ if response.success:
207
+ print("✅ Success! Device updated.")
208
+ # Use updated device for subsequent calls
209
+
210
+
211
+ if __name__ == "__main__":
212
+ asyncio.run(main())
213
+ ```
214
+
215
+ ## Documentation
216
+
217
+ The detailed documentation is available in the `docs/` directory:
218
+
219
+ 1. **[Getting Started](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/01_getting_started.md)**: Installation and First Steps.
220
+ 2. **[API Structure & Concepts](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/02_api_structure.md)**: Understanding the Flat Architecture.
221
+ 3. **[Authentication & Connection](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/03_auth_reference.md)**: Tokens, Sessions, and Thread-Safety.
222
+ 4. **[Models Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/04_models_reference.md)**: Devices, Features, and Controls.
223
+ 5. **[Client Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/05_client_reference.md)**: The `ViClient` class methods.
224
+ 6. **[CLI Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/06_cli_reference.md)**: Using the command line interface.
225
+ 7. **[Exceptions Reference](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/07_exceptions_reference.md)**: Handling errors.
226
+ 8. **[Architecture Guide](https://github.com/ignazhabibi/vi_api_client/blob/main/docs/08_architecture.md)**: System structure,
227
+ responsibilities, data flows, and diagrams explained for developers and
228
+ non-specialists.
@@ -0,0 +1,111 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "vi_api_client"
7
+ version = "6.1.1"
8
+ description = "Async Python client for Viessmann Climate Solutions API"
9
+ readme = "README.md"
10
+ authors = [
11
+ { name = "Michael" },
12
+ ]
13
+ license = "MIT"
14
+ license-files = ["LICENSE"]
15
+ keywords = [
16
+ "api-client",
17
+ "asyncio",
18
+ "heat-pump",
19
+ "heating",
20
+ "home-assistant",
21
+ "viessmann",
22
+ ]
23
+ classifiers = [
24
+ "Development Status :: 5 - Production/Stable",
25
+ "Framework :: AsyncIO",
26
+ "Intended Audience :: Developers",
27
+ "Operating System :: OS Independent",
28
+ "Programming Language :: Python :: 3",
29
+ "Programming Language :: Python :: 3 :: Only",
30
+ "Programming Language :: Python :: 3.14",
31
+ "Programming Language :: Python :: 3.15",
32
+ "Topic :: Home Automation",
33
+ "Typing :: Typed",
34
+ ]
35
+ requires-python = ">=3.14"
36
+ dependencies = [
37
+ "aiohttp>=3.13.3",
38
+ ]
39
+
40
+ [project.urls]
41
+ Homepage = "https://github.com/ignazhabibi/vi_api_client"
42
+ Documentation = "https://github.com/ignazhabibi/vi_api_client/tree/main/docs"
43
+ Issues = "https://github.com/ignazhabibi/vi_api_client/issues"
44
+ Changelog = "https://github.com/ignazhabibi/vi_api_client/releases"
45
+
46
+ [project.optional-dependencies]
47
+ dev = [
48
+ "aiointercept>=0.1.12",
49
+ "build>=1.4",
50
+ "pytest>=9",
51
+ "pytest-asyncio>=1.3",
52
+ "pytest-cov>=7.1",
53
+ "pyright==1.1.414",
54
+ "pre-commit==4.7.0",
55
+ "ruff==0.17.4",
56
+ ]
57
+
58
+ [project.scripts]
59
+ vi-client = "vi_api_client.cli:main"
60
+
61
+ [tool.setuptools.package-data]
62
+ vi_api_client = ["py.typed"]
63
+
64
+ [tool.ruff]
65
+ line-length = 88
66
+ target-version = "py314"
67
+
68
+ [tool.ruff.lint]
69
+ select = [
70
+ "D", # pydocstyle
71
+ "E", # pycodestyle error
72
+ "W", # pycodestyle warning
73
+ "F", # pyflakes
74
+ "I", # isort
75
+ "UP", # pyupgrade
76
+ "B", # flake8-bugbear
77
+ "SIM", # flake8-simplify
78
+ "PL", # pylint
79
+ "RUF", # ruff specific
80
+ "S" # flake8-bandit (security)
81
+ ]
82
+
83
+ ignore = [
84
+ "D100", # Missing docstring in public module
85
+ "D104", # Missing docstring in public package
86
+ "D105", # Missing docstring in magic method
87
+ "D203", # 1 blank line required before class docstring
88
+ "D213", # Multi-line docstring summary should start at the second line
89
+ "PLR2004", # Magic value used
90
+ ]
91
+
92
+ [tool.ruff.lint.per-file-ignores]
93
+ "tests/*" = [
94
+ "D", "PLR0913", "PLR0917", "PLR2004", "E501",
95
+ # Tests assert, use placeholder tokens, and run the CLI as a subprocess.
96
+ "S101", "S105", "S106", "S603",
97
+ ]
98
+ # Repository scripts run fixed tool commands and parse the local coverage.xml.
99
+ "scripts/*" = ["S314", "S603"]
100
+
101
+ [tool.ruff.lint.pydocstyle]
102
+ convention = "google"
103
+
104
+ [tool.ruff.lint.isort]
105
+ combine-as-imports = true
106
+
107
+ [tool.pyright]
108
+ include = ["src", "tests"]
109
+ exclude = [".venv", "build", "dist"]
110
+ pythonVersion = "3.14"
111
+ typeCheckingMode = "standard"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+