python-bsblan 2.2.4__tar.gz → 3.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 (86) hide show
  1. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/codeql.yaml +2 -2
  2. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/linting.yaml +6 -6
  3. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/release.yaml +3 -2
  4. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/tests.yaml +3 -3
  5. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/typing.yaml +1 -1
  6. python_bsblan-3.0.0/.nvmrc +1 -0
  7. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/PKG-INFO +1 -1
  8. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/examples/control.py +121 -26
  9. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/package-lock.json +4 -4
  10. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/package.json +1 -1
  11. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/pyproject.toml +15 -13
  12. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/src/bsblan/__init__.py +6 -0
  13. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/src/bsblan/bsblan.py +201 -4
  14. python_bsblan-3.0.0/src/bsblan/constants.py +244 -0
  15. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/src/bsblan/models.py +41 -8
  16. python_bsblan-3.0.0/src/bsblan/py.typed +0 -0
  17. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/dict_version.json +1 -1
  18. python_bsblan-3.0.0/tests/fixtures/time.json +15 -0
  19. python_bsblan-3.0.0/tests/test_bsblan_edge_cases.py +108 -0
  20. python_bsblan-3.0.0/tests/test_hot_water_additional.py +289 -0
  21. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_hotwater_state.py +50 -54
  22. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_state.py +29 -29
  23. python_bsblan-3.0.0/tests/test_time.py +170 -0
  24. python_bsblan-3.0.0/tests/test_utility_edge_cases.py +45 -0
  25. python_bsblan-3.0.0/uv.lock +2316 -0
  26. python_bsblan-2.2.4/.nvmrc +0 -1
  27. python_bsblan-2.2.4/src/bsblan/constants.py +0 -187
  28. python_bsblan-2.2.4/uv.lock +0 -1939
  29. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.editorconfig +0 -0
  30. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.gitattributes +0 -0
  31. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/CODE_OF_CONDUCT.md +0 -0
  32. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/CONTRIBUTING.md +0 -0
  33. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/ISSUE_TEMPLATE/PULL_REQUEST_TEMPLATE.md +0 -0
  34. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  35. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  36. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/LICENSE.md +0 -0
  37. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/labels.yml +0 -0
  38. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/release-drafter.yml +0 -0
  39. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/renovate.json +0 -0
  40. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/labels.yaml +0 -0
  41. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/lock.yaml +0 -0
  42. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/pr-labels.yaml +0 -0
  43. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/release-drafter.yaml +0 -0
  44. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.github/workflows/stale.yaml +0 -0
  45. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.gitignore +0 -0
  46. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.pre-commit-config.yaml +0 -0
  47. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.prettierignore +0 -0
  48. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/.yamllint +0 -0
  49. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/README.md +0 -0
  50. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/examples/ruff.toml +0 -0
  51. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/sonar-project.properties +0 -0
  52. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/src/bsblan/exceptions.py +0 -0
  53. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/src/bsblan/utility.py +0 -0
  54. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/__init__.py +0 -0
  55. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/conftest.py +0 -0
  56. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/device.json +0 -0
  57. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/hot_water_state.json +0 -0
  58. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/info.json +0 -0
  59. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/password.txt +0 -0
  60. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/sensor.json +0 -0
  61. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/state.json +0 -0
  62. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/static_state.json +0 -0
  63. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/thermostat_hvac.json +0 -0
  64. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/fixtures/thermostat_temp.json +0 -0
  65. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/ruff.toml +0 -0
  66. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_api_initialization.py +0 -0
  67. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_api_validation.py +0 -0
  68. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_auth.py +0 -0
  69. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_bsblan.py +0 -0
  70. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_configuration.py +0 -0
  71. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_context_manager.py +0 -0
  72. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_device.py +0 -0
  73. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_dhw_time_switch.py +0 -0
  74. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_entity_info.py +0 -0
  75. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_info.py +0 -0
  76. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_initialization.py +0 -0
  77. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_reset_validation.py +0 -0
  78. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_sensor.py +0 -0
  79. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_set_hotwater.py +0 -0
  80. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_static_state.py +0 -0
  81. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_temperature_unit.py +0 -0
  82. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_temperature_validation.py +0 -0
  83. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_thermostat.py +0 -0
  84. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_utility.py +0 -0
  85. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_utility_additional.py +0 -0
  86. {python_bsblan-2.2.4 → python_bsblan-3.0.0}/tests/test_version_errors.py +0 -0
@@ -19,6 +19,6 @@ jobs:
19
19
  - name: ⤵️ Check out code from GitHub
20
20
  uses: actions/checkout@v4.2.2
21
21
  - name: 🏗 Initialize CodeQL
22
- uses: github/codeql-action/init@v3.28.18
22
+ uses: github/codeql-action/init@v3.29.8
23
23
  - name: 🚀 Perform CodeQL Analysis
24
- uses: github/codeql-action/analyze@v3.28.18
24
+ uses: github/codeql-action/analyze@v3.29.8
@@ -18,7 +18,7 @@ jobs:
18
18
  - name: ⤵️ Check out code from GitHub
19
19
  uses: actions/checkout@v4.2.2
20
20
  - name: 🏗 Set up uv
21
- uses: astral-sh/setup-uv@v4
21
+ uses: astral-sh/setup-uv@v6
22
22
  with:
23
23
  enable-cache: true
24
24
  - name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
@@ -38,7 +38,7 @@ jobs:
38
38
  - name: ⤵️ Check out code from GitHub
39
39
  uses: actions/checkout@v4.2.2
40
40
  - name: 🏗 Set up uv
41
- uses: astral-sh/setup-uv@v4
41
+ uses: astral-sh/setup-uv@v6
42
42
  with:
43
43
  enable-cache: true
44
44
  - name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
@@ -60,7 +60,7 @@ jobs:
60
60
  - name: ⤵️ Check out code from GitHub
61
61
  uses: actions/checkout@v4.2.2
62
62
  - name: 🏗 Set up uv
63
- uses: astral-sh/setup-uv@v4
63
+ uses: astral-sh/setup-uv@v6
64
64
  with:
65
65
  enable-cache: true
66
66
  - name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
@@ -104,7 +104,7 @@ jobs:
104
104
  - name: ⤵️ Check out code from GitHub
105
105
  uses: actions/checkout@v4.2.2
106
106
  - name: 🏗 Set up uv
107
- uses: astral-sh/setup-uv@v4
107
+ uses: astral-sh/setup-uv@v6
108
108
  with:
109
109
  enable-cache: true
110
110
  - name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
@@ -124,7 +124,7 @@ jobs:
124
124
  - name: ⤵️ Check out code from GitHub
125
125
  uses: actions/checkout@v4.2.2
126
126
  - name: 🏗 Set up uv
127
- uses: astral-sh/setup-uv@v4
127
+ uses: astral-sh/setup-uv@v6
128
128
  with:
129
129
  enable-cache: true
130
130
  - name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
@@ -144,7 +144,7 @@ jobs:
144
144
  - name: ⤵️ Check out code from GitHub
145
145
  uses: actions/checkout@v4.2.2
146
146
  - name: 🏗 Set up uv
147
- uses: astral-sh/setup-uv@v4
147
+ uses: astral-sh/setup-uv@v6
148
148
  with:
149
149
  enable-cache: true
150
150
  - name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
@@ -24,7 +24,7 @@ jobs:
24
24
  - name: ⤵️ Check out code from GitHub
25
25
  uses: actions/checkout@v4.2.2
26
26
  - name: 🏗 Set up uv
27
- uses: astral-sh/setup-uv@v4
27
+ uses: astral-sh/setup-uv@v6
28
28
  with:
29
29
  enable-cache: true
30
30
  - name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
@@ -48,7 +48,7 @@ jobs:
48
48
  verbose: true
49
49
  print-hash: true
50
50
  - name: ✍️ Sign published artifacts
51
- uses: sigstore/gh-action-sigstore-python@v3.0.0
51
+ uses: sigstore/gh-action-sigstore-python@v3.0.1
52
52
  with:
53
53
  inputs: ./dist/*.tar.gz ./dist/*.whl
54
54
  release-signing-artifacts: false
@@ -114,6 +114,7 @@ jobs:
114
114
  if [ $waited_time -ge $max_wait_time ]; then
115
115
  echo "Error: Files not ready after $max_wait_time seconds."
116
116
  exit 1
117
+ fi
117
118
  - name: 📋 List signature files explicitly
118
119
  id: list-files
119
120
  run: |
@@ -21,7 +21,7 @@ jobs:
21
21
  - name: ⤵️ Check out code from GitHub
22
22
  uses: actions/checkout@v4.2.2
23
23
  - name: 🏗 Set up uv
24
- uses: astral-sh/setup-uv@v4
24
+ uses: astral-sh/setup-uv@v6
25
25
  with:
26
26
  enable-cache: true
27
27
  - name: 🏗 Set up Python ${{ matrix.python }}
@@ -49,9 +49,9 @@ jobs:
49
49
  with:
50
50
  fetch-depth: 0
51
51
  - name: ⬇️ Download coverage data
52
- uses: actions/download-artifact@v4.3.0
52
+ uses: actions/download-artifact@v5.0.0
53
53
  - name: 🏗 Set up uv
54
- uses: astral-sh/setup-uv@v4
54
+ uses: astral-sh/setup-uv@v6
55
55
  with:
56
56
  enable-cache: true
57
57
  - name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
@@ -18,7 +18,7 @@ jobs:
18
18
  - name: ⤵️ Check out code from GitHub
19
19
  uses: actions/checkout@v4.2.2
20
20
  - name: 🏗 Set up uv
21
- uses: astral-sh/setup-uv@v4
21
+ uses: astral-sh/setup-uv@v6
22
22
  with:
23
23
  enable-cache: true
24
24
  - name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
@@ -0,0 +1 @@
1
+ 22.18.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-bsblan
3
- Version: 2.2.4
3
+ Version: 3.0.0
4
4
  Summary: Asynchronous Python client for BSBLAN API
5
5
  Project-URL: Homepage, https://github.com/liudger/python-bsblan
6
6
  Project-URL: Repository, https://github.com/liudger/python-bsblan
@@ -1,16 +1,28 @@
1
1
  # pylint: disable=W0621
2
- """Asynchronous Python client for BSBLan."""
2
+ """Asynchronous Python client for BSBLan.
3
+
4
+ This example demonstrates the optimized hot water functionality:
5
+ - HotWaterState: Essential parameters for frequent polling (6 fields)
6
+ - HotWaterConfig: Configuration parameters checked less frequently (15 fields)
7
+ - HotWaterSchedule: Time program schedules checked occasionally (8 fields)
8
+
9
+ This three-tier approach reduces API calls by 79% for regular monitoring.
10
+ """
3
11
 
4
12
  from __future__ import annotations
5
13
 
6
14
  import asyncio
7
15
  import os
16
+ from datetime import datetime
8
17
  from typing import Any
9
18
 
10
19
  from bsblan import (
11
20
  BSBLAN,
12
21
  BSBLANConfig,
13
22
  Device,
23
+ DeviceTime,
24
+ HotWaterConfig,
25
+ HotWaterSchedule,
14
26
  HotWaterState,
15
27
  Info,
16
28
  Sensor,
@@ -88,6 +100,21 @@ async def print_sensor(sensor: Sensor) -> None:
88
100
  print_attributes("Sensor Information", attributes)
89
101
 
90
102
 
103
+ async def print_device_time(device_time: DeviceTime) -> None:
104
+ """Print device time information.
105
+
106
+ Args:
107
+ device_time (DeviceTime): The device time information from the BSBLan device.
108
+
109
+ """
110
+ attributes = {
111
+ "Current Time": await get_attribute(device_time.time, "value", "N/A"),
112
+ "Time Unit": await get_attribute(device_time.time, "unit", "N/A"),
113
+ "Time Description": await get_attribute(device_time.time, "desc", "N/A"),
114
+ }
115
+ print_attributes("Device Time", attributes)
116
+
117
+
91
118
  async def print_device_info(device: Device, info: Info) -> None:
92
119
  """Print device and general information.
93
120
 
@@ -128,11 +155,11 @@ async def print_static_state(static_state: StaticState) -> None:
128
155
 
129
156
 
130
157
  async def print_hot_water_state(hot_water_state: HotWaterState) -> None:
131
- """Print hot water state information.
158
+ """Print essential hot water state information.
132
159
 
133
160
  Args:
134
- hot_water_state (HotWaterState): The hot water state information from the
135
- BSBLan device.
161
+ hot_water_state (HotWaterState): The essential hot water state information
162
+ from the BSBLan device (optimized for frequent polling).
136
163
 
137
164
  """
138
165
  attributes = {
@@ -146,41 +173,82 @@ async def print_hot_water_state(hot_water_state: HotWaterState) -> None:
146
173
  hot_water_state.reduced_setpoint, "value", "N/A"
147
174
  ),
148
175
  "Release": await get_attribute(hot_water_state.release, "desc", "N/A"),
176
+ "Current Temperature": await get_attribute(
177
+ hot_water_state.dhw_actual_value_top_temperature, "value", "N/A"
178
+ ),
179
+ "DHW Pump State": await get_attribute(
180
+ hot_water_state.state_dhw_pump, "desc", "N/A"
181
+ ),
182
+ }
183
+ print_attributes("Hot Water State (Essential)", attributes)
184
+
185
+
186
+ async def print_hot_water_config(hot_water_config: HotWaterConfig) -> None:
187
+ """Print hot water configuration information.
188
+
189
+ Args:
190
+ hot_water_config (HotWaterConfig): The hot water configuration information
191
+ from the BSBLan device (checked less frequently).
192
+
193
+ """
194
+ attributes = {
195
+ "Nominal Setpoint Max": await get_attribute(
196
+ hot_water_config.nominal_setpoint_max, "value", "N/A"
197
+ ),
149
198
  "Legionella Function": await get_attribute(
150
- hot_water_state.legionella_function, "desc", "N/A"
199
+ hot_water_config.legionella_function, "desc", "N/A"
200
+ ),
201
+ "Legionella Setpoint": await get_attribute(
202
+ hot_water_config.legionella_setpoint, "value", "N/A"
151
203
  ),
152
204
  "Legionella Periodicity": await get_attribute(
153
- hot_water_state.legionella_periodicity, "value", "N/A"
205
+ hot_water_config.legionella_periodicity, "value", "N/A"
154
206
  ),
155
- "Legionella Setpoint": await get_attribute(
156
- hot_water_state.legionella_setpoint, "value", "N/A"
207
+ "Circulation Pump Release": await get_attribute(
208
+ hot_water_config.dhw_circulation_pump_release, "desc", "N/A"
157
209
  ),
158
- "Current Temperature": await get_attribute(
159
- hot_water_state.dhw_actual_value_top_temperature, "value", "N/A"
210
+ "Circulation Setpoint": await get_attribute(
211
+ hot_water_config.dhw_circulation_setpoint, "value", "N/A"
212
+ ),
213
+ }
214
+ print_attributes("Hot Water Configuration", attributes)
215
+
216
+
217
+ async def print_hot_water_schedule(hot_water_schedule: HotWaterSchedule) -> None:
218
+ """Print hot water schedule information.
219
+
220
+ Args:
221
+ hot_water_schedule (HotWaterSchedule): The hot water schedule information
222
+ from the BSBLan device (time programs).
223
+
224
+ """
225
+ attributes = {
226
+ "Monday": await get_attribute(
227
+ hot_water_schedule.dhw_time_program_monday, "value", "N/A"
160
228
  ),
161
- "Time Program Monday": await get_attribute(
162
- hot_water_state.dhw_time_program_monday, "value", "N/A"
229
+ "Tuesday": await get_attribute(
230
+ hot_water_schedule.dhw_time_program_tuesday, "value", "N/A"
163
231
  ),
164
- "Time Program Tuesday": await get_attribute(
165
- hot_water_state.dhw_time_program_tuesday, "value", "N/A"
232
+ "Wednesday": await get_attribute(
233
+ hot_water_schedule.dhw_time_program_wednesday, "value", "N/A"
166
234
  ),
167
- "Time Program Wednesday": await get_attribute(
168
- hot_water_state.dhw_time_program_wednesday, "value", "N/A"
235
+ "Thursday": await get_attribute(
236
+ hot_water_schedule.dhw_time_program_thursday, "value", "N/A"
169
237
  ),
170
- "Time Program Thursday": await get_attribute(
171
- hot_water_state.dhw_time_program_thursday, "value", "N/A"
238
+ "Friday": await get_attribute(
239
+ hot_water_schedule.dhw_time_program_friday, "value", "N/A"
172
240
  ),
173
- "Time Program Friday": await get_attribute(
174
- hot_water_state.dhw_time_program_friday, "value", "N/A"
241
+ "Saturday": await get_attribute(
242
+ hot_water_schedule.dhw_time_program_saturday, "value", "N/A"
175
243
  ),
176
- "Time Program Saturday": await get_attribute(
177
- hot_water_state.dhw_time_program_saturday, "value", "N/A"
244
+ "Sunday": await get_attribute(
245
+ hot_water_schedule.dhw_time_program_sunday, "value", "N/A"
178
246
  ),
179
- "Time Program Sunday": await get_attribute(
180
- hot_water_state.dhw_time_program_sunday, "value", "N/A"
247
+ "Standard Values": await get_attribute(
248
+ hot_water_schedule.dhw_time_program_standard_values, "value", "N/A"
181
249
  ),
182
250
  }
183
- print_attributes("Hot Water State", attributes)
251
+ print_attributes("Hot Water Schedule", attributes)
184
252
 
185
253
 
186
254
  async def main() -> None:
@@ -216,14 +284,32 @@ async def main() -> None:
216
284
  info: Info = await bsblan.info()
217
285
  await print_device_info(device, info)
218
286
 
287
+ # Get and print device time
288
+ device_time: DeviceTime = await bsblan.time()
289
+ await print_device_time(device_time)
290
+
219
291
  # Get and print static state
220
292
  static_state: StaticState = await bsblan.static_values()
221
293
  await print_static_state(static_state)
222
294
 
223
- # Get hot water state
295
+ # Get hot water state (essential parameters for frequent polling)
224
296
  hot_water_state: HotWaterState = await bsblan.hot_water_state()
225
297
  await print_hot_water_state(hot_water_state)
226
298
 
299
+ # Get hot water configuration (checked less frequently)
300
+ try:
301
+ hot_water_config: HotWaterConfig = await bsblan.hot_water_config()
302
+ await print_hot_water_config(hot_water_config)
303
+ except Exception as e: # noqa: BLE001
304
+ print(f"Hot water configuration not available: {e}")
305
+
306
+ # Get hot water schedule (time programs)
307
+ try:
308
+ hot_water_schedule: HotWaterSchedule = await bsblan.hot_water_schedule()
309
+ await print_hot_water_schedule(hot_water_schedule)
310
+ except Exception as e: # noqa: BLE001
311
+ print(f"Hot water schedule not available: {e}")
312
+
227
313
  # Example: Set DHW time program for Monday
228
314
  print("\nSetting DHW time program for Monday to 13:00-14:00")
229
315
 
@@ -232,6 +318,15 @@ async def main() -> None:
232
318
  )
233
319
  await bsblan.set_hot_water(dhw_time_programs=dhw_programs)
234
320
 
321
+ # Example: Set device time
322
+ print("\nSetting device time to current system time")
323
+ # Get current local system time and format it for BSB-LAN (DD.MM.YYYY HH:MM:SS)
324
+ # Note: Using local time intentionally to sync BSB-LAN with system clock
325
+ current_time = datetime.now().replace(microsecond=0) # noqa: DTZ005
326
+ formatted_time = current_time.strftime("%d.%m.%Y %H:%M:%S")
327
+ print(f"Current system time: {formatted_time}")
328
+ await bsblan.set_time(formatted_time)
329
+
235
330
 
236
331
  if __name__ == "__main__":
237
332
  asyncio.run(main())
@@ -12,13 +12,13 @@
12
12
  "url-parse": "1.5.10"
13
13
  },
14
14
  "devDependencies": {
15
- "prettier": "3.5.3"
15
+ "prettier": "3.6.2"
16
16
  }
17
17
  },
18
18
  "node_modules/prettier": {
19
- "version": "3.5.3",
20
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
21
- "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
19
+ "version": "3.6.2",
20
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
21
+ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
22
22
  "dev": true,
23
23
  "license": "MIT",
24
24
  "bin": {
@@ -9,7 +9,7 @@
9
9
  "author": "WJL van Rootselaar <liudgervr@gmail.com>",
10
10
  "license": "MIT",
11
11
  "devDependencies": {
12
- "prettier": "3.5.3"
12
+ "prettier": "3.6.2"
13
13
  },
14
14
  "dependencies": {
15
15
  "url-parse": "1.5.10"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-bsblan"
3
- version = "2.2.4"
3
+ version = "3.0.0"
4
4
  description = "Asynchronous Python client for BSBLAN API"
5
5
  authors = [
6
6
  {name = "Willem-Jan van Rootselaar", email = "liudgervr@gmail.com"}
@@ -163,26 +163,28 @@ build-backend = "hatchling.build"
163
163
  [dependency-groups]
164
164
  dev = [
165
165
  "aresponses==3.0.0",
166
- "bandit==1.8.3",
166
+ "bandit==1.8.6",
167
167
  "black==25.1.0",
168
168
  "blacken-docs==1.19.1",
169
169
  "codespell==2.4.1",
170
170
  "covdefaults==2.3.0",
171
- "coverage==7.8.2",
171
+ "coverage==7.10.3",
172
172
  "darglint==1.8.1",
173
- "flake8==7.2.0",
173
+ "flake8==7.3.0",
174
174
  "flake8-simplify==0.22.0",
175
+ # hatch is required to support type hinting and proper packaging of the py.typed file.
176
+ "hatch>=1.14.1",
175
177
  "isort==6.0.1",
176
- "mypy==1.16.0",
177
- "pre-commit==4.2.0",
178
- "pre-commit-hooks==5.0.0",
179
- "pylint==3.3.7",
178
+ "mypy==1.17.1",
179
+ "pre-commit==4.3.0",
180
+ "pre-commit-hooks==6.0.0",
181
+ "pylint==3.3.8",
180
182
  "pytest>=8.3.5",
181
- "pytest-asyncio==1.0.0",
182
- "pytest-cov==6.1.1",
183
- "pyupgrade==3.19.1",
184
- "ruff==0.11.13",
185
- "safety==3.5.1",
183
+ "pytest-asyncio==1.1.0",
184
+ "pytest-cov==6.2.1",
185
+ "pyupgrade==3.20.0",
186
+ "ruff==0.12.8",
187
+ "safety==3.6.0",
186
188
  "vulture==2.14",
187
189
  "yamllint==1.37.1",
188
190
  ]
@@ -4,7 +4,10 @@ from .bsblan import BSBLAN, BSBLANConfig
4
4
  from .exceptions import BSBLANAuthError, BSBLANConnectionError, BSBLANError
5
5
  from .models import (
6
6
  Device,
7
+ DeviceTime,
7
8
  DHWTimeSwitchPrograms,
9
+ HotWaterConfig,
10
+ HotWaterSchedule,
8
11
  HotWaterState,
9
12
  Info,
10
13
  Sensor,
@@ -20,6 +23,9 @@ __all__ = [
20
23
  "BSBLANError",
21
24
  "DHWTimeSwitchPrograms",
22
25
  "Device",
26
+ "DeviceTime",
27
+ "HotWaterConfig",
28
+ "HotWaterSchedule",
23
29
  "HotWaterState",
24
30
  "Info",
25
31
  "Sensor",