python-bsblan 2.2.5__tar.gz → 3.1.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.
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/codeql.yaml +3 -3
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/labels.yaml +1 -1
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/linting.yaml +12 -12
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/release.yaml +3 -3
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/tests.yaml +6 -6
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/typing.yaml +2 -2
- python_bsblan-3.1.0/.nvmrc +1 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/PKG-INFO +1 -1
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/examples/control.py +123 -28
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/package-lock.json +4 -4
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/package.json +1 -1
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/pyproject.toml +30 -15
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/src/bsblan/__init__.py +6 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/src/bsblan/bsblan.py +212 -13
- python_bsblan-3.1.0/src/bsblan/constants.py +244 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/src/bsblan/models.py +41 -8
- python_bsblan-3.1.0/src/bsblan/py.typed +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/dict_version.json +1 -1
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/thermostat_hvac.json +1 -1
- python_bsblan-3.1.0/tests/fixtures/time.json +15 -0
- python_bsblan-3.1.0/tests/test_bsblan_edge_cases.py +108 -0
- python_bsblan-3.1.0/tests/test_constants.py +152 -0
- python_bsblan-3.1.0/tests/test_hot_water_additional.py +289 -0
- python_bsblan-3.1.0/tests/test_hotwater_state.py +114 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_set_hotwater.py +10 -10
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_state.py +29 -29
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_thermostat.py +2 -2
- python_bsblan-3.1.0/tests/test_time.py +170 -0
- python_bsblan-3.1.0/tests/test_utility_edge_cases.py +45 -0
- python_bsblan-3.1.0/uv.lock +2342 -0
- python_bsblan-2.2.5/.nvmrc +0 -1
- python_bsblan-2.2.5/src/bsblan/constants.py +0 -187
- python_bsblan-2.2.5/tests/test_hotwater_state.py +0 -121
- python_bsblan-2.2.5/uv.lock +0 -1939
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.editorconfig +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.gitattributes +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/CODE_OF_CONDUCT.md +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/CONTRIBUTING.md +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/ISSUE_TEMPLATE/PULL_REQUEST_TEMPLATE.md +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/LICENSE.md +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/labels.yml +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/release-drafter.yml +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/renovate.json +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/lock.yaml +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/pr-labels.yaml +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/release-drafter.yaml +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.github/workflows/stale.yaml +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.gitignore +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.pre-commit-config.yaml +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.prettierignore +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/.yamllint +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/README.md +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/examples/ruff.toml +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/sonar-project.properties +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/src/bsblan/exceptions.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/src/bsblan/utility.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/__init__.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/conftest.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/device.json +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/hot_water_state.json +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/info.json +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/password.txt +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/sensor.json +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/state.json +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/static_state.json +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/fixtures/thermostat_temp.json +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/ruff.toml +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_api_initialization.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_api_validation.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_auth.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_bsblan.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_configuration.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_context_manager.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_device.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_dhw_time_switch.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_entity_info.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_info.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_initialization.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_reset_validation.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_sensor.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_static_state.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_temperature_unit.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_temperature_validation.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_utility.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_utility_additional.py +0 -0
- {python_bsblan-2.2.5 → python_bsblan-3.1.0}/tests/test_version_errors.py +0 -0
|
@@ -17,8 +17,8 @@ jobs:
|
|
|
17
17
|
runs-on: ubuntu-latest
|
|
18
18
|
steps:
|
|
19
19
|
- name: ⤵️ Check out code from GitHub
|
|
20
|
-
uses: actions/checkout@
|
|
20
|
+
uses: actions/checkout@v5.0.0
|
|
21
21
|
- name: 🏗 Initialize CodeQL
|
|
22
|
-
uses: github/codeql-action/init@v3.
|
|
22
|
+
uses: github/codeql-action/init@v3.30.3
|
|
23
23
|
- name: 🚀 Perform CodeQL Analysis
|
|
24
|
-
uses: github/codeql-action/analyze@v3.
|
|
24
|
+
uses: github/codeql-action/analyze@v3.30.3
|
|
@@ -16,9 +16,9 @@ jobs:
|
|
|
16
16
|
runs-on: ubuntu-latest
|
|
17
17
|
steps:
|
|
18
18
|
- name: ⤵️ Check out code from GitHub
|
|
19
|
-
uses: actions/checkout@
|
|
19
|
+
uses: actions/checkout@v5.0.0
|
|
20
20
|
- name: 🏗 Set up uv
|
|
21
|
-
uses: astral-sh/setup-uv@
|
|
21
|
+
uses: astral-sh/setup-uv@v6
|
|
22
22
|
with:
|
|
23
23
|
enable-cache: true
|
|
24
24
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -36,9 +36,9 @@ jobs:
|
|
|
36
36
|
runs-on: ubuntu-latest
|
|
37
37
|
steps:
|
|
38
38
|
- name: ⤵️ Check out code from GitHub
|
|
39
|
-
uses: actions/checkout@
|
|
39
|
+
uses: actions/checkout@v5.0.0
|
|
40
40
|
- name: 🏗 Set up uv
|
|
41
|
-
uses: astral-sh/setup-uv@
|
|
41
|
+
uses: astral-sh/setup-uv@v6
|
|
42
42
|
with:
|
|
43
43
|
enable-cache: true
|
|
44
44
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -58,9 +58,9 @@ jobs:
|
|
|
58
58
|
runs-on: ubuntu-latest
|
|
59
59
|
steps:
|
|
60
60
|
- name: ⤵️ Check out code from GitHub
|
|
61
|
-
uses: actions/checkout@
|
|
61
|
+
uses: actions/checkout@v5.0.0
|
|
62
62
|
- name: 🏗 Set up uv
|
|
63
|
-
uses: astral-sh/setup-uv@
|
|
63
|
+
uses: astral-sh/setup-uv@v6
|
|
64
64
|
with:
|
|
65
65
|
enable-cache: true
|
|
66
66
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -102,9 +102,9 @@ jobs:
|
|
|
102
102
|
runs-on: ubuntu-latest
|
|
103
103
|
steps:
|
|
104
104
|
- name: ⤵️ Check out code from GitHub
|
|
105
|
-
uses: actions/checkout@
|
|
105
|
+
uses: actions/checkout@v5.0.0
|
|
106
106
|
- name: 🏗 Set up uv
|
|
107
|
-
uses: astral-sh/setup-uv@
|
|
107
|
+
uses: astral-sh/setup-uv@v6
|
|
108
108
|
with:
|
|
109
109
|
enable-cache: true
|
|
110
110
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -122,9 +122,9 @@ jobs:
|
|
|
122
122
|
runs-on: ubuntu-latest
|
|
123
123
|
steps:
|
|
124
124
|
- name: ⤵️ Check out code from GitHub
|
|
125
|
-
uses: actions/checkout@
|
|
125
|
+
uses: actions/checkout@v5.0.0
|
|
126
126
|
- name: 🏗 Set up uv
|
|
127
|
-
uses: astral-sh/setup-uv@
|
|
127
|
+
uses: astral-sh/setup-uv@v6
|
|
128
128
|
with:
|
|
129
129
|
enable-cache: true
|
|
130
130
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -142,9 +142,9 @@ jobs:
|
|
|
142
142
|
runs-on: ubuntu-latest
|
|
143
143
|
steps:
|
|
144
144
|
- name: ⤵️ Check out code from GitHub
|
|
145
|
-
uses: actions/checkout@
|
|
145
|
+
uses: actions/checkout@v5.0.0
|
|
146
146
|
- name: 🏗 Set up uv
|
|
147
|
-
uses: astral-sh/setup-uv@
|
|
147
|
+
uses: astral-sh/setup-uv@v6
|
|
148
148
|
with:
|
|
149
149
|
enable-cache: true
|
|
150
150
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -22,9 +22,9 @@ jobs:
|
|
|
22
22
|
id-token: write
|
|
23
23
|
steps:
|
|
24
24
|
- name: ⤵️ Check out code from GitHub
|
|
25
|
-
uses: actions/checkout@
|
|
25
|
+
uses: actions/checkout@v5.0.0
|
|
26
26
|
- name: 🏗 Set up uv
|
|
27
|
-
uses: astral-sh/setup-uv@
|
|
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.
|
|
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
|
|
@@ -19,9 +19,9 @@ jobs:
|
|
|
19
19
|
python: ["3.11", "3.12"]
|
|
20
20
|
steps:
|
|
21
21
|
- name: ⤵️ Check out code from GitHub
|
|
22
|
-
uses: actions/checkout@
|
|
22
|
+
uses: actions/checkout@v5.0.0
|
|
23
23
|
- name: 🏗 Set up uv
|
|
24
|
-
uses: astral-sh/setup-uv@
|
|
24
|
+
uses: astral-sh/setup-uv@v6
|
|
25
25
|
with:
|
|
26
26
|
enable-cache: true
|
|
27
27
|
- name: 🏗 Set up Python ${{ matrix.python }}
|
|
@@ -45,13 +45,13 @@ jobs:
|
|
|
45
45
|
needs: pytest
|
|
46
46
|
steps:
|
|
47
47
|
- name: ⤵️ Check out code from GitHub
|
|
48
|
-
uses: actions/checkout@
|
|
48
|
+
uses: actions/checkout@v5.0.0
|
|
49
49
|
with:
|
|
50
50
|
fetch-depth: 0
|
|
51
51
|
- name: ⬇️ Download coverage data
|
|
52
|
-
uses: actions/download-artifact@
|
|
52
|
+
uses: actions/download-artifact@v5.0.0
|
|
53
53
|
- name: 🏗 Set up uv
|
|
54
|
-
uses: astral-sh/setup-uv@
|
|
54
|
+
uses: astral-sh/setup-uv@v6
|
|
55
55
|
with:
|
|
56
56
|
enable-cache: true
|
|
57
57
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -66,7 +66,7 @@ jobs:
|
|
|
66
66
|
uv run coverage combine coverage*/.coverage*
|
|
67
67
|
uv run coverage xml -i
|
|
68
68
|
- name: 🚀 Upload coverage report
|
|
69
|
-
uses: codecov/codecov-action@v5.
|
|
69
|
+
uses: codecov/codecov-action@v5.5.1
|
|
70
70
|
with:
|
|
71
71
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
72
72
|
- name: SonarCloud Scan
|
|
@@ -16,9 +16,9 @@ jobs:
|
|
|
16
16
|
runs-on: ubuntu-latest
|
|
17
17
|
steps:
|
|
18
18
|
- name: ⤵️ Check out code from GitHub
|
|
19
|
-
uses: actions/checkout@
|
|
19
|
+
uses: actions/checkout@v5.0.0
|
|
20
20
|
- name: 🏗 Set up uv
|
|
21
|
-
uses: astral-sh/setup-uv@
|
|
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.19.0
|
|
@@ -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 (5 fields)
|
|
6
|
+
- HotWaterConfig: Configuration parameters checked less frequently (16 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
|
|
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 = {
|
|
@@ -142,45 +169,86 @@ async def print_hot_water_state(hot_water_state: HotWaterState) -> None:
|
|
|
142
169
|
"Nominal Setpoint": await get_attribute(
|
|
143
170
|
hot_water_state.nominal_setpoint, "value", "N/A"
|
|
144
171
|
),
|
|
172
|
+
"Release": await get_attribute(hot_water_state.release, "desc", "N/A"),
|
|
173
|
+
"Current Temperature": await get_attribute(
|
|
174
|
+
hot_water_state.dhw_actual_value_top_temperature, "value", "N/A"
|
|
175
|
+
),
|
|
176
|
+
"DHW Pump State": await get_attribute(
|
|
177
|
+
hot_water_state.state_dhw_pump, "desc", "N/A"
|
|
178
|
+
),
|
|
179
|
+
}
|
|
180
|
+
print_attributes("Hot Water State (Essential)", attributes)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
async def print_hot_water_config(hot_water_config: HotWaterConfig) -> None:
|
|
184
|
+
"""Print hot water configuration information.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
hot_water_config (HotWaterConfig): The hot water configuration information
|
|
188
|
+
from the BSBLan device (checked less frequently).
|
|
189
|
+
|
|
190
|
+
"""
|
|
191
|
+
attributes = {
|
|
192
|
+
"Nominal Setpoint Max": await get_attribute(
|
|
193
|
+
hot_water_config.nominal_setpoint_max, "value", "N/A"
|
|
194
|
+
),
|
|
145
195
|
"Reduced Setpoint": await get_attribute(
|
|
146
|
-
|
|
196
|
+
hot_water_config.reduced_setpoint, "value", "N/A"
|
|
147
197
|
),
|
|
148
|
-
"Release": await get_attribute(hot_water_state.release, "desc", "N/A"),
|
|
149
198
|
"Legionella Function": await get_attribute(
|
|
150
|
-
|
|
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
|
-
|
|
205
|
+
hot_water_config.legionella_periodicity, "value", "N/A"
|
|
154
206
|
),
|
|
155
|
-
"
|
|
156
|
-
|
|
207
|
+
"Circulation Pump Release": await get_attribute(
|
|
208
|
+
hot_water_config.dhw_circulation_pump_release, "desc", "N/A"
|
|
157
209
|
),
|
|
158
|
-
"
|
|
159
|
-
|
|
210
|
+
"Circulation Setpoint": await get_attribute(
|
|
211
|
+
hot_water_config.dhw_circulation_setpoint, "value", "N/A"
|
|
160
212
|
),
|
|
161
|
-
|
|
162
|
-
|
|
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"
|
|
163
228
|
),
|
|
164
|
-
"
|
|
165
|
-
|
|
229
|
+
"Tuesday": await get_attribute(
|
|
230
|
+
hot_water_schedule.dhw_time_program_tuesday, "value", "N/A"
|
|
166
231
|
),
|
|
167
|
-
"
|
|
168
|
-
|
|
232
|
+
"Wednesday": await get_attribute(
|
|
233
|
+
hot_water_schedule.dhw_time_program_wednesday, "value", "N/A"
|
|
169
234
|
),
|
|
170
|
-
"
|
|
171
|
-
|
|
235
|
+
"Thursday": await get_attribute(
|
|
236
|
+
hot_water_schedule.dhw_time_program_thursday, "value", "N/A"
|
|
172
237
|
),
|
|
173
|
-
"
|
|
174
|
-
|
|
238
|
+
"Friday": await get_attribute(
|
|
239
|
+
hot_water_schedule.dhw_time_program_friday, "value", "N/A"
|
|
175
240
|
),
|
|
176
|
-
"
|
|
177
|
-
|
|
241
|
+
"Saturday": await get_attribute(
|
|
242
|
+
hot_water_schedule.dhw_time_program_saturday, "value", "N/A"
|
|
178
243
|
),
|
|
179
|
-
"
|
|
180
|
-
|
|
244
|
+
"Sunday": await get_attribute(
|
|
245
|
+
hot_water_schedule.dhw_time_program_sunday, "value", "N/A"
|
|
246
|
+
),
|
|
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
|
|
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 - Broad exception for demo purposes
|
|
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 - Broad exception for demo purposes
|
|
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 for this demo to sync BSB-LAN
|
|
325
|
+
current_time = datetime.now().replace(microsecond=0) # noqa: DTZ005 - Demo uses local time
|
|
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.
|
|
15
|
+
"prettier": "3.6.2"
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"node_modules/prettier": {
|
|
19
|
-
"version": "3.
|
|
20
|
-
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.
|
|
21
|
-
"integrity": "sha512-
|
|
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": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-bsblan"
|
|
3
|
-
version = "
|
|
3
|
+
version = "3.1.0"
|
|
4
4
|
description = "Asynchronous Python client for BSBLAN API"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Willem-Jan van Rootselaar", email = "liudgervr@gmail.com"}
|
|
@@ -46,11 +46,24 @@ packages = ["src/bsblan"]
|
|
|
46
46
|
|
|
47
47
|
[tool.coverage.run]
|
|
48
48
|
plugins = ["covdefaults"]
|
|
49
|
-
source = ["bsblan"]
|
|
49
|
+
source = ["src/bsblan"]
|
|
50
|
+
omit = [
|
|
51
|
+
"tests/*",
|
|
52
|
+
"*/tests/*",
|
|
53
|
+
"test_*",
|
|
54
|
+
"*test*"
|
|
55
|
+
]
|
|
50
56
|
|
|
51
57
|
[tool.coverage.report]
|
|
52
58
|
show_missing = true
|
|
53
59
|
fail_under = 53
|
|
60
|
+
exclude_lines = [
|
|
61
|
+
"pragma: no cover",
|
|
62
|
+
"def __repr__",
|
|
63
|
+
"raise AssertionError",
|
|
64
|
+
"raise NotImplementedError",
|
|
65
|
+
"if __name__ == .__main__.:",
|
|
66
|
+
]
|
|
54
67
|
|
|
55
68
|
[tool.mypy]
|
|
56
69
|
# Specify the target platform details in config, so your developers are
|
|
@@ -163,26 +176,28 @@ build-backend = "hatchling.build"
|
|
|
163
176
|
[dependency-groups]
|
|
164
177
|
dev = [
|
|
165
178
|
"aresponses==3.0.0",
|
|
166
|
-
"bandit==1.8.
|
|
179
|
+
"bandit==1.8.6",
|
|
167
180
|
"black==25.1.0",
|
|
168
|
-
"blacken-docs==1.
|
|
181
|
+
"blacken-docs==1.20.0",
|
|
169
182
|
"codespell==2.4.1",
|
|
170
183
|
"covdefaults==2.3.0",
|
|
171
|
-
"coverage==7.
|
|
184
|
+
"coverage==7.10.6",
|
|
172
185
|
"darglint==1.8.1",
|
|
173
|
-
"flake8==7.
|
|
186
|
+
"flake8==7.3.0",
|
|
174
187
|
"flake8-simplify==0.22.0",
|
|
188
|
+
# hatch is required to support type hinting and proper packaging of the py.typed file.
|
|
189
|
+
"hatch>=1.14.1",
|
|
175
190
|
"isort==6.0.1",
|
|
176
|
-
"mypy==1.
|
|
177
|
-
"pre-commit==4.
|
|
178
|
-
"pre-commit-hooks==
|
|
179
|
-
"pylint==3.3.
|
|
191
|
+
"mypy==1.18.1",
|
|
192
|
+
"pre-commit==4.3.0",
|
|
193
|
+
"pre-commit-hooks==6.0.0",
|
|
194
|
+
"pylint==3.3.8",
|
|
180
195
|
"pytest>=8.3.5",
|
|
181
|
-
"pytest-asyncio==1.
|
|
182
|
-
"pytest-cov==6.
|
|
183
|
-
"pyupgrade==3.
|
|
184
|
-
"ruff==0.
|
|
185
|
-
"safety==3.
|
|
196
|
+
"pytest-asyncio==1.1.0",
|
|
197
|
+
"pytest-cov==6.3.0",
|
|
198
|
+
"pyupgrade==3.20.0",
|
|
199
|
+
"ruff==0.13.0",
|
|
200
|
+
"safety==3.6.1",
|
|
186
201
|
"vulture==2.14",
|
|
187
202
|
"yamllint==1.37.1",
|
|
188
203
|
]
|
|
@@ -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",
|