python-bsblan 5.2.0__tar.gz → 6.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.
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/codeql.yaml +2 -2
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/dependency-review.yaml +1 -1
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/docs.yaml +1 -1
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/linting.yaml +2 -2
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/release-drafter.yaml +1 -1
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/release.yaml +1 -1
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/scorecard.yml +1 -1
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/tests.yaml +4 -4
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/typing.yaml +1 -1
- python_bsblan-6.0.0/.nvmrc +1 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/PKG-INFO +1 -1
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/docs/api/client.md +2 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/docs/getting-started.md +36 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/examples/control.py +34 -14
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/pyproject.toml +5 -5
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/src/bsblan/bsblan.py +160 -64
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/src/bsblan/constants.py +26 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/src/bsblan/models.py +23 -3
- python_bsblan-6.0.0/tests/fixtures/pps_device.json +16 -0
- python_bsblan-6.0.0/tests/fixtures/pps_state.json +23 -0
- python_bsblan-6.0.0/tests/fixtures/pps_static_values.json +16 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_circuit.py +49 -120
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_device.py +5 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_include_parameter.py +31 -0
- python_bsblan-6.0.0/tests/test_pps.py +380 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_time.py +13 -1
- python_bsblan-5.2.0/.nvmrc +0 -1
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.editorconfig +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.gitattributes +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/CODE_OF_CONDUCT.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/CONTRIBUTING.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/ISSUE_TEMPLATE/PULL_REQUEST_TEMPLATE.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/SECURITY.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/copilot-instructions.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/labels.yml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/prompts/add-parameter.prompt.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/prompts/code-review.prompt.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/release-drafter.yml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/renovate.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/skills/bsblan-parameters/SKILL.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/skills/bsblan-testing/SKILL.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/auto-approve-renovate.yml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/labels.yaml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/lock.yaml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/pr-labels.yaml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/workflows/stale.yaml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.github/zizmor.yml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.gitignore +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.pre-commit-config.yaml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.prettierignore +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/.yamllint +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/AGENTS.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/CLAUDE.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/LICENSE.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/Makefile +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/README.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/docs/api/constants.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/docs/api/exceptions.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/docs/api/models.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/docs/index.md +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/examples/discovery.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/examples/fetch_param.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/examples/profile_init.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/examples/ruff.toml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/examples/speed_test.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/mkdocs.yml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/package-lock.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/package.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/sonar-project.properties +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/src/bsblan/__init__.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/src/bsblan/exceptions.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/src/bsblan/py.typed +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/src/bsblan/utility.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/__init__.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/conftest.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/device.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/dict_version.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/hot_water_state.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/info.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/password.txt +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/sensor.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/state.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/state_circuit2.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/static_state.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/static_state_circuit2.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/thermostat_hvac.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/thermostat_temp.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/fixtures/time.json +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/ruff.toml +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_api_initialization.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_api_validation.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_auth.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_backoff_retry.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_bsblan.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_bsblan_edge_cases.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_configuration.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_constants.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_context_manager.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_dhw_time_switch.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_entity_info.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_entity_info_ha.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_heating_schedule.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_hot_water_additional.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_hotwater_state.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_info.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_initialization.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_read_parameters.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_reset_validation.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_schedule_models.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_sensor.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_set_heating_schedule.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_set_hot_water_schedule.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_set_hotwater.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_state.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_static_state.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_temperature_unit.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_temperature_validation.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_thermostat.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_utility.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_utility_additional.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_utility_edge_cases.py +0 -0
- {python_bsblan-5.2.0 → python_bsblan-6.0.0}/tests/test_version_errors.py +0 -0
|
@@ -27,6 +27,6 @@ jobs:
|
|
|
27
27
|
with:
|
|
28
28
|
persist-credentials: false
|
|
29
29
|
- name: 🏗 Initialize CodeQL
|
|
30
|
-
uses: github/codeql-action/init@
|
|
30
|
+
uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
|
|
31
31
|
- name: 🚀 Perform CodeQL Analysis
|
|
32
|
-
uses: github/codeql-action/analyze@
|
|
32
|
+
uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
|
|
@@ -18,4 +18,4 @@ jobs:
|
|
|
18
18
|
persist-credentials: false
|
|
19
19
|
- name: 👀 Dependency review
|
|
20
20
|
# yamllint disable-line rule:line-length
|
|
21
|
-
uses: actions/dependency-review-action@
|
|
21
|
+
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
|
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
with:
|
|
28
28
|
persist-credentials: false
|
|
29
29
|
- name: 🏗 Set up uv
|
|
30
|
-
uses: astral-sh/setup-uv@
|
|
30
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
31
31
|
with:
|
|
32
32
|
enable-cache: true
|
|
33
33
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -25,7 +25,7 @@ jobs:
|
|
|
25
25
|
with:
|
|
26
26
|
persist-credentials: false
|
|
27
27
|
- name: 🏗 Set up uv
|
|
28
|
-
uses: astral-sh/setup-uv@
|
|
28
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
29
29
|
with:
|
|
30
30
|
enable-cache: true
|
|
31
31
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -49,7 +49,7 @@ jobs:
|
|
|
49
49
|
with:
|
|
50
50
|
persist-credentials: false
|
|
51
51
|
- name: 🏗 Set up uv
|
|
52
|
-
uses: astral-sh/setup-uv@
|
|
52
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
53
53
|
with:
|
|
54
54
|
enable-cache: true
|
|
55
55
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -36,7 +36,7 @@ jobs:
|
|
|
36
36
|
steps:
|
|
37
37
|
- name: 🚀 Run Release Drafter
|
|
38
38
|
# yamllint disable-line rule:line-length
|
|
39
|
-
uses: release-drafter/release-drafter@
|
|
39
|
+
uses: release-drafter/release-drafter@c2e2804cc59f45f57076a99af580d0fedb697927 # v7.3.0
|
|
40
40
|
with:
|
|
41
41
|
prerelease: ${{ github.event.inputs.prerelease == 'true' }}
|
|
42
42
|
prerelease-identifier: ${{ github.event.inputs.prerelease_identifier }}
|
|
@@ -29,7 +29,7 @@ jobs:
|
|
|
29
29
|
with:
|
|
30
30
|
persist-credentials: false
|
|
31
31
|
- name: 🏗 Set up uv
|
|
32
|
-
uses: astral-sh/setup-uv@
|
|
32
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
33
33
|
with:
|
|
34
34
|
enable-cache: false
|
|
35
35
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -66,6 +66,6 @@ jobs:
|
|
|
66
66
|
# Upload the results to GitHub's code scanning dashboard (optional).
|
|
67
67
|
- name: "Upload to code-scanning"
|
|
68
68
|
# yamllint disable-line rule:line-length
|
|
69
|
-
uses: github/codeql-action/upload-sarif@
|
|
69
|
+
uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5
|
|
70
70
|
with:
|
|
71
71
|
sarif_file: results.sarif
|
|
@@ -33,7 +33,7 @@ jobs:
|
|
|
33
33
|
with:
|
|
34
34
|
persist-credentials: false
|
|
35
35
|
- name: 🏗 Set up uv
|
|
36
|
-
uses: astral-sh/setup-uv@
|
|
36
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
37
37
|
with:
|
|
38
38
|
enable-cache: true
|
|
39
39
|
- name: 🏗 Set up Python ${{ matrix.python }}
|
|
@@ -68,7 +68,7 @@ jobs:
|
|
|
68
68
|
- name: ⬇️ Download coverage data
|
|
69
69
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
70
70
|
- name: 🏗 Set up uv
|
|
71
|
-
uses: astral-sh/setup-uv@
|
|
71
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
72
72
|
with:
|
|
73
73
|
enable-cache: true
|
|
74
74
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -84,7 +84,7 @@ jobs:
|
|
|
84
84
|
uv run python -m coverage xml -i
|
|
85
85
|
- name: 🚀 Upload coverage report
|
|
86
86
|
if: env.HAS_CODECOV_TOKEN == 'true'
|
|
87
|
-
uses: codecov/codecov-action@
|
|
87
|
+
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
|
|
88
88
|
with:
|
|
89
89
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
90
90
|
- name: ℹ️ Skip Codecov upload (missing token)
|
|
@@ -93,7 +93,7 @@ jobs:
|
|
|
93
93
|
- name: SonarQube Cloud Scan
|
|
94
94
|
if: env.HAS_SONAR_TOKEN == 'true' && (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork)
|
|
95
95
|
# yamllint disable-line rule:line-length
|
|
96
|
-
uses: SonarSource/sonarqube-scan-action@
|
|
96
|
+
uses: SonarSource/sonarqube-scan-action@59db25f34e16620e48ab4bb9e4a5dce155cb5432 # v8.0
|
|
97
97
|
env:
|
|
98
98
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
99
99
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
persist-credentials: false
|
|
28
28
|
- name: 🏗 Set up uv
|
|
29
29
|
# yamllint disable-line rule:line-length
|
|
30
|
-
uses: astral-sh/setup-uv@
|
|
30
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
31
31
|
with:
|
|
32
32
|
enable-cache: true
|
|
33
33
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24.15.0
|
|
@@ -63,6 +63,42 @@ async def main() -> None:
|
|
|
63
63
|
asyncio.run(main())
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
## PPS bus support
|
|
67
|
+
|
|
68
|
+
PPS bus devices are detected from the device metadata returned by BSB-LAN. The
|
|
69
|
+
client provides minimal climate support for PPS devices through the same climate
|
|
70
|
+
methods used by BSB/LPB devices.
|
|
71
|
+
|
|
72
|
+
Supported PPS climate operations:
|
|
73
|
+
|
|
74
|
+
- `state()` for `hvac_mode`, `target_temperature`, and `current_temperature`
|
|
75
|
+
- `static_values()` for `min_temp` and `max_temp`
|
|
76
|
+
- `thermostat()` for target temperature and HVAC mode
|
|
77
|
+
- `get_available_circuits()`, which returns `[1]` when the single PPS
|
|
78
|
+
climate circuit is available, otherwise `[]`; PPS devices only ever expose
|
|
79
|
+
circuit `1`
|
|
80
|
+
|
|
81
|
+
PPS devices currently have these limitations:
|
|
82
|
+
|
|
83
|
+
- Only circuit `1` is supported.
|
|
84
|
+
- `time()` and `set_time()` are not supported for PPS devices.
|
|
85
|
+
- `thermostat(hvac_mode=2)` is not supported on PPS devices. Valid PPS modes
|
|
86
|
+
are `0` (off), `1` (auto), and `3` (heat/manual).
|
|
87
|
+
- Hot water and schedule helpers are intended for BSB/LPB devices.
|
|
88
|
+
|
|
89
|
+
Check `supports_time_sync` before showing or calling time synchronization in
|
|
90
|
+
applications:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
async with BSBLAN(config) as client:
|
|
94
|
+
device = client.device_info or await client.device()
|
|
95
|
+
print(f"Bus type: {device.bus or 'unknown'}")
|
|
96
|
+
|
|
97
|
+
if client.supports_time_sync:
|
|
98
|
+
device_time = await client.time()
|
|
99
|
+
print(device_time.time.value)
|
|
100
|
+
```
|
|
101
|
+
|
|
66
102
|
## Hot water control
|
|
67
103
|
|
|
68
104
|
```python
|
|
@@ -68,6 +68,16 @@ def print_attributes(title: str, attributes: dict[str, str]) -> None:
|
|
|
68
68
|
print(f"{label}: {value}")
|
|
69
69
|
|
|
70
70
|
|
|
71
|
+
def format_yes_no(*, value: bool) -> str:
|
|
72
|
+
"""Format a boolean as a readable yes/no value."""
|
|
73
|
+
return "yes" if value else "no"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def format_optional(value: Any) -> str:
|
|
77
|
+
"""Format optional device metadata for display."""
|
|
78
|
+
return "N/A" if value is None else str(value)
|
|
79
|
+
|
|
80
|
+
|
|
71
81
|
def get_hvac_action_name(status_code: int) -> str:
|
|
72
82
|
"""Map BSB-LAN parameter 8000 status code to a human-readable HVAC action.
|
|
73
83
|
|
|
@@ -180,6 +190,11 @@ async def print_device_info(device: Device, info: Info) -> None:
|
|
|
180
190
|
"Device Name": device.name or "N/A",
|
|
181
191
|
"Version": device.version or "N/A",
|
|
182
192
|
"Device Identification": device_identification,
|
|
193
|
+
"Bus Type": format_optional(device.bus),
|
|
194
|
+
"Bus Writable Flag": format_optional(device.buswritable),
|
|
195
|
+
"Bus Address": format_optional(device.busaddr),
|
|
196
|
+
"Bus Destination": format_optional(device.busdest),
|
|
197
|
+
"Supports Time Sync": format_yes_no(value=device.supports_time_sync),
|
|
183
198
|
}
|
|
184
199
|
print_attributes("Device Information", attributes)
|
|
185
200
|
|
|
@@ -319,6 +334,11 @@ async def main() -> None:
|
|
|
319
334
|
|
|
320
335
|
# Initialize BSBLAN with the configuration object
|
|
321
336
|
async with BSBLAN(config) as bsblan:
|
|
337
|
+
# Get and print device and general info, including bus metadata
|
|
338
|
+
device: Device = bsblan.device_info or await bsblan.device()
|
|
339
|
+
info: Info = await bsblan.info()
|
|
340
|
+
await print_device_info(device, info)
|
|
341
|
+
|
|
322
342
|
# Get and print state
|
|
323
343
|
state: State = await bsblan.state()
|
|
324
344
|
await print_state(state)
|
|
@@ -335,14 +355,12 @@ async def main() -> None:
|
|
|
335
355
|
sensor: Sensor = await bsblan.sensor()
|
|
336
356
|
await print_sensor(sensor)
|
|
337
357
|
|
|
338
|
-
# Get and print device and general info
|
|
339
|
-
device: Device = await bsblan.device()
|
|
340
|
-
info: Info = await bsblan.info()
|
|
341
|
-
await print_device_info(device, info)
|
|
342
|
-
|
|
343
358
|
# Get and print device time
|
|
344
|
-
|
|
345
|
-
|
|
359
|
+
if bsblan.supports_time_sync:
|
|
360
|
+
device_time: DeviceTime = await bsblan.time()
|
|
361
|
+
await print_device_time(device_time)
|
|
362
|
+
else:
|
|
363
|
+
print("\nDevice time is not available for this bus type")
|
|
346
364
|
|
|
347
365
|
# Get and print static state
|
|
348
366
|
static_state: StaticState = await bsblan.static_values()
|
|
@@ -375,13 +393,15 @@ async def main() -> None:
|
|
|
375
393
|
await bsblan.set_hot_water(SetHotWaterParam(dhw_time_programs=dhw_programs))
|
|
376
394
|
|
|
377
395
|
# Example: Set device time
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
396
|
+
if bsblan.supports_time_sync:
|
|
397
|
+
print("\nSetting device time to current system time")
|
|
398
|
+
# Get current local system time and format it for BSB-LAN.
|
|
399
|
+
current_time = datetime.now().replace(microsecond=0) # noqa: DTZ005
|
|
400
|
+
formatted_time = current_time.strftime("%d.%m.%Y %H:%M:%S")
|
|
401
|
+
print(f"Current system time: {formatted_time}")
|
|
402
|
+
await bsblan.set_time(formatted_time)
|
|
403
|
+
else:
|
|
404
|
+
print("\nSkipping device time sync for this bus type")
|
|
385
405
|
|
|
386
406
|
|
|
387
407
|
if __name__ == "__main__":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-bsblan"
|
|
3
|
-
version = "
|
|
3
|
+
version = "6.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"}
|
|
@@ -185,18 +185,18 @@ build-backend = "hatchling.build"
|
|
|
185
185
|
dev = [
|
|
186
186
|
"aresponses==3.0.0",
|
|
187
187
|
"bandit==1.9.4",
|
|
188
|
-
"black==26.
|
|
188
|
+
"black==26.5.1",
|
|
189
189
|
"blacken-docs==1.20.0",
|
|
190
190
|
"codespell==2.4.2",
|
|
191
191
|
"covdefaults==2.3.0",
|
|
192
|
-
"coverage==7.
|
|
192
|
+
"coverage==7.14.0",
|
|
193
193
|
"darglint==1.8.1",
|
|
194
194
|
"flake8==7.3.0",
|
|
195
195
|
"flake8-simplify==0.30.0",
|
|
196
196
|
# hatch is required to support type hinting and proper packaging of the py.typed file.
|
|
197
197
|
"hatch>=1.14.1",
|
|
198
198
|
"isort==8.0.1",
|
|
199
|
-
"ty==0.0.
|
|
199
|
+
"ty==0.0.38",
|
|
200
200
|
"prek>=0.3.3",
|
|
201
201
|
"pre-commit-hooks==6.0.0",
|
|
202
202
|
"pylint==4.0.5",
|
|
@@ -205,7 +205,7 @@ dev = [
|
|
|
205
205
|
"pytest-cov==7.1.0",
|
|
206
206
|
"pytest-xdist>=3.8.0",
|
|
207
207
|
"pyupgrade==3.21.2",
|
|
208
|
-
"ruff==0.15.
|
|
208
|
+
"ruff==0.15.13",
|
|
209
209
|
"safety==3.7.0",
|
|
210
210
|
"vulture==2.16",
|
|
211
211
|
"yamllint==1.38.0",
|