python-bsblan 5.1.2__tar.gz → 5.1.3__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.1.2 → python_bsblan-5.1.3}/.github/renovate.json +1 -2
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/codeql.yaml +2 -2
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/release-drafter.yaml +1 -1
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/tests.yaml +2 -2
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.gitignore +3 -0
- python_bsblan-5.1.3/.nvmrc +1 -0
- python_bsblan-5.1.3/Makefile +20 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/PKG-INFO +14 -2
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/README.md +13 -1
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/examples/speed_test.py +2 -85
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/pyproject.toml +16 -8
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/src/bsblan/bsblan.py +13 -15
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/src/bsblan/constants.py +5 -53
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/src/bsblan/models.py +0 -1
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/dict_version.json +1 -2
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/state.json +0 -12
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/state_circuit2.json +2 -14
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_api_validation.py +0 -2
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_circuit.py +12 -110
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_constants.py +0 -2
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_hotwater_state.py +0 -2
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_initialization.py +0 -2
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_state.py +1 -6
- python_bsblan-5.1.2/.nvmrc +0 -1
- python_bsblan-5.1.2/uv.lock +0 -2381
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.editorconfig +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.gitattributes +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/CODE_OF_CONDUCT.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/CONTRIBUTING.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/ISSUE_TEMPLATE/PULL_REQUEST_TEMPLATE.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/copilot-instructions.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/labels.yml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/prompts/add-parameter.prompt.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/prompts/code-review.prompt.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/release-drafter.yml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/skills/bsblan-parameters/SKILL.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/skills/bsblan-testing/SKILL.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/auto-approve-renovate.yml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/labels.yaml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/linting.yaml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/lock.yaml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/pr-labels.yaml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/release.yaml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.github/workflows/stale.yaml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.pre-commit-config.yaml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.prettierignore +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/.yamllint +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/AGENTS.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/CLAUDE.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/LICENSE.md +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/examples/control.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/examples/discovery.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/examples/fetch_param.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/examples/profile_init.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/examples/ruff.toml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/package-lock.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/package.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/sonar-project.properties +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/src/bsblan/__init__.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/src/bsblan/exceptions.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/src/bsblan/py.typed +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/src/bsblan/utility.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/__init__.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/conftest.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/device.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/hot_water_state.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/info.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/password.txt +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/sensor.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/static_state.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/static_state_circuit2.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/thermostat_hvac.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/thermostat_temp.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/fixtures/time.json +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/ruff.toml +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_api_initialization.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_auth.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_backoff_retry.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_bsblan.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_bsblan_edge_cases.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_configuration.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_context_manager.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_device.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_dhw_time_switch.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_entity_info.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_entity_info_ha.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_hot_water_additional.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_include_parameter.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_info.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_read_parameters.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_reset_validation.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_schedule_models.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_sensor.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_set_hot_water_schedule.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_set_hotwater.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_static_state.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_temperature_unit.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_temperature_validation.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_thermostat.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_time.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_utility.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_utility_additional.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_utility_edge_cases.py +0 -0
- {python_bsblan-5.1.2 → python_bsblan-5.1.3}/tests/test_version_errors.py +0 -0
|
@@ -24,6 +24,6 @@ jobs:
|
|
|
24
24
|
- name: ⤵️ Check out code from GitHub
|
|
25
25
|
uses: actions/checkout@v6.0.2
|
|
26
26
|
- name: 🏗 Initialize CodeQL
|
|
27
|
-
uses: github/codeql-action/init@v4.
|
|
27
|
+
uses: github/codeql-action/init@v4.34.1
|
|
28
28
|
- name: 🚀 Perform CodeQL Analysis
|
|
29
|
-
uses: github/codeql-action/analyze@v4.
|
|
29
|
+
uses: github/codeql-action/analyze@v4.34.1
|
|
@@ -34,7 +34,7 @@ jobs:
|
|
|
34
34
|
runs-on: ubuntu-latest
|
|
35
35
|
steps:
|
|
36
36
|
- name: 🚀 Run Release Drafter
|
|
37
|
-
uses: release-drafter/release-drafter@
|
|
37
|
+
uses: release-drafter/release-drafter@v7.1.1
|
|
38
38
|
with:
|
|
39
39
|
prerelease: ${{ github.event.inputs.prerelease == 'true' }}
|
|
40
40
|
prerelease-identifier: ${{ github.event.inputs.prerelease_identifier }}
|
|
@@ -58,7 +58,7 @@ jobs:
|
|
|
58
58
|
with:
|
|
59
59
|
fetch-depth: 0
|
|
60
60
|
- name: ⬇️ Download coverage data
|
|
61
|
-
uses: actions/download-artifact@v8.0.
|
|
61
|
+
uses: actions/download-artifact@v8.0.1
|
|
62
62
|
- name: 🏗 Set up uv
|
|
63
63
|
uses: astral-sh/setup-uv@v7
|
|
64
64
|
with:
|
|
@@ -76,7 +76,7 @@ jobs:
|
|
|
76
76
|
uv run python -m coverage xml -i
|
|
77
77
|
- name: 🚀 Upload coverage report
|
|
78
78
|
if: env.HAS_CODECOV_TOKEN == 'true'
|
|
79
|
-
uses: codecov/codecov-action@v5.5.
|
|
79
|
+
uses: codecov/codecov-action@v5.5.3
|
|
80
80
|
with:
|
|
81
81
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
82
82
|
- name: ℹ️ Skip Codecov upload (missing token)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24.14.1
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.PHONY: setup lint test coverage help
|
|
2
|
+
|
|
3
|
+
.DEFAULT_GOAL := help
|
|
4
|
+
|
|
5
|
+
help: ## Show this help message
|
|
6
|
+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
|
|
7
|
+
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
|
|
8
|
+
|
|
9
|
+
setup: ## Install dev dependencies and git hooks
|
|
10
|
+
uv sync --dev
|
|
11
|
+
uv run prek install
|
|
12
|
+
|
|
13
|
+
lint: ## Run all pre-commit hooks
|
|
14
|
+
uv run prek run --all-files
|
|
15
|
+
|
|
16
|
+
test: ## Run tests
|
|
17
|
+
uv run pytest
|
|
18
|
+
|
|
19
|
+
coverage: ## Run tests with coverage report
|
|
20
|
+
uv run pytest --cov=src/bsblan --cov-report=term-missing
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-bsblan
|
|
3
|
-
Version: 5.1.
|
|
3
|
+
Version: 5.1.3
|
|
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
|
|
@@ -182,9 +182,21 @@ To install all packages, including all development requirements:
|
|
|
182
182
|
|
|
183
183
|
```bash
|
|
184
184
|
npm install
|
|
185
|
-
|
|
185
|
+
make setup
|
|
186
186
|
```
|
|
187
187
|
|
|
188
|
+
### Makefile Targets
|
|
189
|
+
|
|
190
|
+
A `Makefile` is provided for common development tasks. Run `make help` to
|
|
191
|
+
see all available targets:
|
|
192
|
+
|
|
193
|
+
| Command | Description |
|
|
194
|
+
|-----------------|--------------------------------------|
|
|
195
|
+
| `make setup` | Install dev dependencies & git hooks |
|
|
196
|
+
| `make lint` | Run all pre-commit hooks |
|
|
197
|
+
| `make test` | Run tests |
|
|
198
|
+
| `make coverage` | Run tests with coverage report |
|
|
199
|
+
|
|
188
200
|
As this repository uses [prek][prek] (a faster, Rust-based drop-in replacement
|
|
189
201
|
for pre-commit), all changes are linted and tested with each commit. You can
|
|
190
202
|
run all checks and tests manually, using the following command:
|
|
@@ -150,9 +150,21 @@ To install all packages, including all development requirements:
|
|
|
150
150
|
|
|
151
151
|
```bash
|
|
152
152
|
npm install
|
|
153
|
-
|
|
153
|
+
make setup
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
+
### Makefile Targets
|
|
157
|
+
|
|
158
|
+
A `Makefile` is provided for common development tasks. Run `make help` to
|
|
159
|
+
see all available targets:
|
|
160
|
+
|
|
161
|
+
| Command | Description |
|
|
162
|
+
|-----------------|--------------------------------------|
|
|
163
|
+
| `make setup` | Install dev dependencies & git hooks |
|
|
164
|
+
| `make lint` | Run all pre-commit hooks |
|
|
165
|
+
| `make test` | Run tests |
|
|
166
|
+
| `make coverage` | Run tests with coverage report |
|
|
167
|
+
|
|
156
168
|
As this repository uses [prek][prek] (a faster, Rust-based drop-in replacement
|
|
157
169
|
for pre-commit), all changes are linted and tested with each commit. You can
|
|
158
170
|
run all checks and tests manually, using the following command:
|
|
@@ -4,7 +4,6 @@ Compares different approaches using pluggable benchmark suites:
|
|
|
4
4
|
- basic: Original tests (parallel calls, read_parameters, filtering)
|
|
5
5
|
- scalability: Large parameter set tests
|
|
6
6
|
- dual-circuit: Single vs parallel calls for dual heating circuit params
|
|
7
|
-
- triple-circuit: Same idea extended to 3 heating circuits
|
|
8
7
|
- hot-water: Hot water parameter group loading tests
|
|
9
8
|
|
|
10
9
|
Usage:
|
|
@@ -56,29 +55,20 @@ STATIC_PARAMS = ["714", "716"] # Min/max temp setpoints
|
|
|
56
55
|
ALL_PARAMS = INFO_PARAMS + STATIC_PARAMS
|
|
57
56
|
|
|
58
57
|
# Heating circuit 1 (700-series)
|
|
59
|
-
HC1_PARAMS = ["700", "710", "900", "8000", "8740"
|
|
58
|
+
HC1_PARAMS = ["700", "710", "900", "8000", "8740"]
|
|
60
59
|
|
|
61
60
|
# Heating circuit 2 (1000-series) — mirrors HC1 with offset
|
|
62
|
-
HC2_PARAMS = ["1000", "1010", "1200", "8001", "
|
|
63
|
-
|
|
64
|
-
# Heating circuit 3 (1300-series) — mirrors HC1 with offset
|
|
65
|
-
HC3_PARAMS = ["1300", "1310", "1500", "8002", "8742", "8751"]
|
|
61
|
+
HC2_PARAMS = ["1000", "1010", "1200", "8001", "8770"]
|
|
66
62
|
|
|
67
63
|
# Static values per circuit
|
|
68
64
|
HC1_STATIC_PARAMS = ["714", "716"]
|
|
69
65
|
HC2_STATIC_PARAMS = ["1014", "1016"]
|
|
70
|
-
HC3_STATIC_PARAMS = ["1314", "1316"]
|
|
71
66
|
|
|
72
67
|
# Combined dual circuit parameter sets
|
|
73
68
|
DUAL_HEATING_PARAMS = HC1_PARAMS + HC2_PARAMS
|
|
74
69
|
DUAL_STATIC_PARAMS = HC1_STATIC_PARAMS + HC2_STATIC_PARAMS
|
|
75
70
|
DUAL_ALL_PARAMS = DUAL_HEATING_PARAMS + DUAL_STATIC_PARAMS
|
|
76
71
|
|
|
77
|
-
# Triple circuit parameter sets
|
|
78
|
-
TRIPLE_HEATING_PARAMS = HC1_PARAMS + HC2_PARAMS + HC3_PARAMS
|
|
79
|
-
TRIPLE_STATIC_PARAMS = HC1_STATIC_PARAMS + HC2_STATIC_PARAMS + HC3_STATIC_PARAMS
|
|
80
|
-
TRIPLE_ALL_PARAMS = TRIPLE_HEATING_PARAMS + TRIPLE_STATIC_PARAMS
|
|
81
|
-
|
|
82
72
|
# Sensor parameters
|
|
83
73
|
SENSOR_PARAMS = ["8700", "8740"]
|
|
84
74
|
|
|
@@ -515,78 +505,6 @@ def build_dual_circuit_suite(bsblan: BSBLAN) -> BenchmarkSuite:
|
|
|
515
505
|
return suite
|
|
516
506
|
|
|
517
507
|
|
|
518
|
-
def build_triple_circuit_suite(bsblan: BSBLAN) -> BenchmarkSuite:
|
|
519
|
-
"""Build the triple heating circuit benchmark suite.
|
|
520
|
-
|
|
521
|
-
Same idea as dual-circuit but for 3 circuits. Most systems have
|
|
522
|
-
at most 2 circuits; HC3 params will return '---' on those
|
|
523
|
-
devices but this still measures the network call overhead.
|
|
524
|
-
"""
|
|
525
|
-
suite = BenchmarkSuite(
|
|
526
|
-
name="Triple Heating Circuit",
|
|
527
|
-
description=(
|
|
528
|
-
"Compare fetching strategies for 3 heating circuits.\n"
|
|
529
|
-
" HC1: " + ", ".join(HC1_PARAMS) + "\n"
|
|
530
|
-
" HC2: " + ", ".join(HC2_PARAMS) + "\n"
|
|
531
|
-
" HC3: " + ", ".join(HC3_PARAMS)
|
|
532
|
-
),
|
|
533
|
-
)
|
|
534
|
-
|
|
535
|
-
suite.add(
|
|
536
|
-
(f"HC1+HC2+HC3 combined — 1 call ({len(TRIPLE_HEATING_PARAMS)} params)"),
|
|
537
|
-
f"1 call ({len(TRIPLE_HEATING_PARAMS)}p)",
|
|
538
|
-
lambda: bsblan.read_parameters(TRIPLE_HEATING_PARAMS),
|
|
539
|
-
param_count=len(TRIPLE_HEATING_PARAMS),
|
|
540
|
-
)
|
|
541
|
-
|
|
542
|
-
suite.add(
|
|
543
|
-
"HC1+HC2+HC3 parallel — 3 calls",
|
|
544
|
-
"3 parallel",
|
|
545
|
-
lambda: asyncio.gather(
|
|
546
|
-
bsblan.read_parameters(HC1_PARAMS),
|
|
547
|
-
bsblan.read_parameters(HC2_PARAMS),
|
|
548
|
-
bsblan.read_parameters(HC3_PARAMS),
|
|
549
|
-
),
|
|
550
|
-
param_count=len(TRIPLE_HEATING_PARAMS),
|
|
551
|
-
)
|
|
552
|
-
|
|
553
|
-
async def _sequential_3() -> None:
|
|
554
|
-
await bsblan.read_parameters(HC1_PARAMS)
|
|
555
|
-
await bsblan.read_parameters(HC2_PARAMS)
|
|
556
|
-
await bsblan.read_parameters(HC3_PARAMS)
|
|
557
|
-
|
|
558
|
-
suite.add(
|
|
559
|
-
"HC1+HC2+HC3 sequential — 3 calls",
|
|
560
|
-
"3 sequential",
|
|
561
|
-
_sequential_3,
|
|
562
|
-
param_count=len(TRIPLE_HEATING_PARAMS),
|
|
563
|
-
)
|
|
564
|
-
|
|
565
|
-
# Full init with static values
|
|
566
|
-
suite.add(
|
|
567
|
-
(f"All circuits + static — 1 call ({len(TRIPLE_ALL_PARAMS)} params)"),
|
|
568
|
-
f"1 call all ({len(TRIPLE_ALL_PARAMS)}p)",
|
|
569
|
-
lambda: bsblan.read_parameters(TRIPLE_ALL_PARAMS),
|
|
570
|
-
param_count=len(TRIPLE_ALL_PARAMS),
|
|
571
|
-
)
|
|
572
|
-
|
|
573
|
-
suite.add(
|
|
574
|
-
"All circuits + static — 6 parallel (heat+static per circ)",
|
|
575
|
-
"6 parallel per section",
|
|
576
|
-
lambda: asyncio.gather(
|
|
577
|
-
bsblan.read_parameters(HC1_PARAMS),
|
|
578
|
-
bsblan.read_parameters(HC2_PARAMS),
|
|
579
|
-
bsblan.read_parameters(HC3_PARAMS),
|
|
580
|
-
bsblan.read_parameters(HC1_STATIC_PARAMS),
|
|
581
|
-
bsblan.read_parameters(HC2_STATIC_PARAMS),
|
|
582
|
-
bsblan.read_parameters(HC3_STATIC_PARAMS),
|
|
583
|
-
),
|
|
584
|
-
param_count=len(TRIPLE_ALL_PARAMS),
|
|
585
|
-
)
|
|
586
|
-
|
|
587
|
-
return suite
|
|
588
|
-
|
|
589
|
-
|
|
590
508
|
def build_hot_water_suite(bsblan: BSBLAN) -> BenchmarkSuite:
|
|
591
509
|
"""Build the hot water parameter benchmark suite."""
|
|
592
510
|
suite = BenchmarkSuite(
|
|
@@ -645,7 +563,6 @@ SUITE_BUILDERS: dict[str, Callable[[BSBLAN], BenchmarkSuite]] = {
|
|
|
645
563
|
"basic": build_basic_suite,
|
|
646
564
|
"scalability": build_scalability_suite,
|
|
647
565
|
"dual-circuit": build_dual_circuit_suite,
|
|
648
|
-
"triple-circuit": build_triple_circuit_suite,
|
|
649
566
|
"hot-water": build_hot_water_suite,
|
|
650
567
|
}
|
|
651
568
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-bsblan"
|
|
3
|
-
version = "5.1.
|
|
3
|
+
version = "5.1.3"
|
|
4
4
|
description = "Asynchronous Python client for BSBLAN API"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Willem-Jan van Rootselaar", email = "liudgervr@gmail.com"}
|
|
@@ -166,6 +166,14 @@ runtime-evaluated-base-classes = ["pydantic.BaseModel"]
|
|
|
166
166
|
[tool.ruff.lint.mccabe]
|
|
167
167
|
max-complexity = 25
|
|
168
168
|
|
|
169
|
+
[[tool.ty.overrides]]
|
|
170
|
+
include = ["tests/**", "**/test_*.py", "examples/**"]
|
|
171
|
+
|
|
172
|
+
[tool.ty.overrides.rules]
|
|
173
|
+
invalid-assignment = "ignore"
|
|
174
|
+
invalid-argument-type = "ignore"
|
|
175
|
+
unresolved-attribute = "ignore"
|
|
176
|
+
|
|
169
177
|
[tool.codespell]
|
|
170
178
|
ignore-words-list = "astroid"
|
|
171
179
|
|
|
@@ -177,29 +185,29 @@ build-backend = "hatchling.build"
|
|
|
177
185
|
dev = [
|
|
178
186
|
"aresponses==3.0.0",
|
|
179
187
|
"bandit==1.9.4",
|
|
180
|
-
"black==26.1
|
|
188
|
+
"black==26.3.1",
|
|
181
189
|
"blacken-docs==1.20.0",
|
|
182
|
-
"codespell==2.4.
|
|
190
|
+
"codespell==2.4.2",
|
|
183
191
|
"covdefaults==2.3.0",
|
|
184
|
-
"coverage==7.13.
|
|
192
|
+
"coverage==7.13.5",
|
|
185
193
|
"darglint==1.8.1",
|
|
186
194
|
"flake8==7.3.0",
|
|
187
195
|
"flake8-simplify==0.30.0",
|
|
188
196
|
# hatch is required to support type hinting and proper packaging of the py.typed file.
|
|
189
197
|
"hatch>=1.14.1",
|
|
190
198
|
"isort==8.0.1",
|
|
191
|
-
"ty==0.0.
|
|
199
|
+
"ty==0.0.25",
|
|
192
200
|
"prek>=0.3.3",
|
|
193
201
|
"pre-commit-hooks==6.0.0",
|
|
194
202
|
"pylint==4.0.5",
|
|
195
203
|
"pytest>=8.3.5",
|
|
196
204
|
"pytest-asyncio==1.3.0",
|
|
197
|
-
"pytest-cov==7.
|
|
205
|
+
"pytest-cov==7.1.0",
|
|
198
206
|
"pytest-xdist>=3.8.0",
|
|
199
207
|
"pyupgrade==3.21.2",
|
|
200
|
-
"ruff==0.15.
|
|
208
|
+
"ruff==0.15.7",
|
|
201
209
|
"safety==3.7.0",
|
|
202
|
-
"vulture==2.
|
|
210
|
+
"vulture==2.15",
|
|
203
211
|
"yamllint==1.38.0",
|
|
204
212
|
"zeroconf>=0.148.0",
|
|
205
213
|
]
|
|
@@ -91,9 +91,7 @@ SectionLiteral = Literal[
|
|
|
91
91
|
"sensor",
|
|
92
92
|
"hot_water",
|
|
93
93
|
"heating_circuit2",
|
|
94
|
-
"heating_circuit3",
|
|
95
94
|
"staticValues_circuit2",
|
|
96
|
-
"staticValues_circuit3",
|
|
97
95
|
]
|
|
98
96
|
|
|
99
97
|
# TypeVar for hot water data models
|
|
@@ -184,10 +182,10 @@ class BSBLAN:
|
|
|
184
182
|
async def get_available_circuits(self) -> list[int]:
|
|
185
183
|
"""Detect which heating circuits are available on the device.
|
|
186
184
|
|
|
187
|
-
Uses a two-step probe for each circuit (1, 2
|
|
185
|
+
Uses a two-step probe for each circuit (1, 2):
|
|
188
186
|
1. Query the operating mode parameter — the response must be
|
|
189
187
|
non-empty and contain actual data.
|
|
190
|
-
2. Query the status parameter (8000/8001
|
|
188
|
+
2. Query the status parameter (8000/8001) — an inactive
|
|
191
189
|
circuit returns ``value="0"`` with ``desc="---"``.
|
|
192
190
|
|
|
193
191
|
A circuit is only considered available when both checks pass.
|
|
@@ -614,7 +612,7 @@ class BSBLAN:
|
|
|
614
612
|
"""Fetch min/max temperature range for a circuit from the device.
|
|
615
613
|
|
|
616
614
|
Args:
|
|
617
|
-
circuit: The heating circuit number (1
|
|
615
|
+
circuit: The heating circuit number (1 or 2).
|
|
618
616
|
|
|
619
617
|
Returns:
|
|
620
618
|
dict with 'min' and 'max' keys (values may be None if unavailable).
|
|
@@ -661,7 +659,7 @@ class BSBLAN:
|
|
|
661
659
|
the staticValues section if not already done.
|
|
662
660
|
|
|
663
661
|
Args:
|
|
664
|
-
circuit: The heating circuit number (1
|
|
662
|
+
circuit: The heating circuit number (1 or 2).
|
|
665
663
|
|
|
666
664
|
Note: Temperature unit is extracted during heating section validation
|
|
667
665
|
from the response (parameter 710), so no extra API call is needed here.
|
|
@@ -680,7 +678,7 @@ class BSBLAN:
|
|
|
680
678
|
self._max_temp = temp_range["max"]
|
|
681
679
|
self._temperature_range_initialized = True
|
|
682
680
|
else:
|
|
683
|
-
# HC2
|
|
681
|
+
# HC2 uses per-circuit storage
|
|
684
682
|
self._circuit_temp_ranges[circuit] = temp_range
|
|
685
683
|
self._circuit_temp_initialized.add(circuit)
|
|
686
684
|
|
|
@@ -1010,9 +1008,9 @@ class BSBLAN:
|
|
|
1010
1008
|
fetches all state parameters. Valid names include:
|
|
1011
1009
|
hvac_mode, target_temperature, hvac_action,
|
|
1012
1010
|
hvac_mode_changeover, current_temperature,
|
|
1013
|
-
|
|
1014
|
-
circuit: The heating circuit number (1
|
|
1015
|
-
Circuit 2
|
|
1011
|
+
room1_temp_setpoint_boost.
|
|
1012
|
+
circuit: The heating circuit number (1 or 2). Defaults to 1.
|
|
1013
|
+
Circuit 2 uses separate parameter IDs but returns the
|
|
1016
1014
|
same State model with the same field names.
|
|
1017
1015
|
|
|
1018
1016
|
Returns:
|
|
@@ -1065,7 +1063,7 @@ class BSBLAN:
|
|
|
1065
1063
|
include: Optional list of parameter names to fetch. If None,
|
|
1066
1064
|
fetches all static parameters. Valid names include:
|
|
1067
1065
|
min_temp, max_temp.
|
|
1068
|
-
circuit: The heating circuit number (1
|
|
1066
|
+
circuit: The heating circuit number (1 or 2). Defaults to 1.
|
|
1069
1067
|
|
|
1070
1068
|
Returns:
|
|
1071
1069
|
StaticState: The static information from the BSBLAN device.
|
|
@@ -1157,7 +1155,7 @@ class BSBLAN:
|
|
|
1157
1155
|
target_temperature (str | None): The target temperature to set.
|
|
1158
1156
|
hvac_mode (int | None): The HVAC mode to set as raw integer value.
|
|
1159
1157
|
Valid values: 0=off, 1=auto, 2=eco, 3=heat.
|
|
1160
|
-
circuit: The heating circuit number (1
|
|
1158
|
+
circuit: The heating circuit number (1 or 2). Defaults to 1.
|
|
1161
1159
|
|
|
1162
1160
|
Example:
|
|
1163
1161
|
# Set HC1 temperature
|
|
@@ -1194,7 +1192,7 @@ class BSBLAN:
|
|
|
1194
1192
|
Args:
|
|
1195
1193
|
target_temperature (str | None): The target temperature to set.
|
|
1196
1194
|
hvac_mode (int | None): The HVAC mode to set as raw integer.
|
|
1197
|
-
circuit: The heating circuit number (1
|
|
1195
|
+
circuit: The heating circuit number (1 or 2).
|
|
1198
1196
|
|
|
1199
1197
|
Returns:
|
|
1200
1198
|
dict[str, Any]: The prepared state for the thermostat.
|
|
@@ -1236,7 +1234,7 @@ class BSBLAN:
|
|
|
1236
1234
|
|
|
1237
1235
|
Args:
|
|
1238
1236
|
target_temperature (str): The target temperature to validate.
|
|
1239
|
-
circuit: The heating circuit number (1
|
|
1237
|
+
circuit: The heating circuit number (1 or 2).
|
|
1240
1238
|
|
|
1241
1239
|
Raises:
|
|
1242
1240
|
BSBLANError: If the temperature range cannot be initialized.
|
|
@@ -1254,7 +1252,7 @@ class BSBLAN:
|
|
|
1254
1252
|
min_temp = self._min_temp
|
|
1255
1253
|
max_temp = self._max_temp
|
|
1256
1254
|
else:
|
|
1257
|
-
# HC2
|
|
1255
|
+
# HC2 uses per-circuit storage
|
|
1258
1256
|
if circuit not in self._circuit_temp_initialized:
|
|
1259
1257
|
await self._initialize_temperature_range(circuit)
|
|
1260
1258
|
|
|
@@ -7,8 +7,8 @@ from typing import Final, TypedDict
|
|
|
7
7
|
|
|
8
8
|
# Supported heating circuits (1-based)
|
|
9
9
|
MIN_CIRCUIT: Final[int] = 1
|
|
10
|
-
MAX_CIRCUIT: Final[int] =
|
|
11
|
-
VALID_CIRCUITS: Final[set[int]] = {1, 2
|
|
10
|
+
MAX_CIRCUIT: Final[int] = 2
|
|
11
|
+
VALID_CIRCUITS: Final[set[int]] = {1, 2}
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
# API Versions
|
|
@@ -20,11 +20,9 @@ class APIConfig(TypedDict):
|
|
|
20
20
|
device: dict[str, str]
|
|
21
21
|
sensor: dict[str, str]
|
|
22
22
|
hot_water: dict[str, str]
|
|
23
|
-
# Multi-circuit sections (heating circuit 2
|
|
23
|
+
# Multi-circuit sections (heating circuit 2)
|
|
24
24
|
heating_circuit2: dict[str, str]
|
|
25
|
-
heating_circuit3: dict[str, str]
|
|
26
25
|
staticValues_circuit2: dict[str, str]
|
|
27
|
-
staticValues_circuit3: dict[str, str]
|
|
28
26
|
|
|
29
27
|
|
|
30
28
|
# Base parameters that exist in all API versions
|
|
@@ -35,7 +33,6 @@ BASE_HEATING_PARAMS: Final[dict[str, str]] = {
|
|
|
35
33
|
# -------
|
|
36
34
|
"8000": "hvac_action",
|
|
37
35
|
"8740": "current_temperature",
|
|
38
|
-
"8749": "room1_thermostat_mode",
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
BASE_STATIC_VALUES_PARAMS: Final[dict[str, str]] = {
|
|
@@ -111,8 +108,7 @@ BASE_HEATING_CIRCUIT2_PARAMS: Final[dict[str, str]] = {
|
|
|
111
108
|
"1200": "hvac_mode_changeover",
|
|
112
109
|
# -------
|
|
113
110
|
"8001": "hvac_action",
|
|
114
|
-
"
|
|
115
|
-
"8750": "room1_thermostat_mode",
|
|
111
|
+
"8770": "current_temperature",
|
|
116
112
|
}
|
|
117
113
|
|
|
118
114
|
BASE_STATIC_VALUES_CIRCUIT2_PARAMS: Final[dict[str, str]] = {
|
|
@@ -131,52 +127,21 @@ V3_STATIC_VALUES_CIRCUIT2_EXTENSIONS: Final[dict[str, str]] = {
|
|
|
131
127
|
"1016": "max_temp",
|
|
132
128
|
}
|
|
133
129
|
|
|
134
|
-
# --- Heating Circuit 3 parameters (1300-series) ---
|
|
135
|
-
# These mirror HC1 (700-series) with an offset of +600
|
|
136
|
-
BASE_HEATING_CIRCUIT3_PARAMS: Final[dict[str, str]] = {
|
|
137
|
-
"1300": "hvac_mode",
|
|
138
|
-
"1310": "target_temperature",
|
|
139
|
-
"1500": "hvac_mode_changeover",
|
|
140
|
-
# -------
|
|
141
|
-
"8002": "hvac_action",
|
|
142
|
-
"8742": "current_temperature",
|
|
143
|
-
"8751": "room1_thermostat_mode",
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
BASE_STATIC_VALUES_CIRCUIT3_PARAMS: Final[dict[str, str]] = {
|
|
147
|
-
"1314": "min_temp",
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
V1_STATIC_VALUES_CIRCUIT3_EXTENSIONS: Final[dict[str, str]] = {
|
|
151
|
-
"1330": "max_temp",
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
V3_HEATING_CIRCUIT3_EXTENSIONS: Final[dict[str, str]] = {
|
|
155
|
-
"1370": "room1_temp_setpoint_boost",
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
V3_STATIC_VALUES_CIRCUIT3_EXTENSIONS: Final[dict[str, str]] = {
|
|
159
|
-
"1316": "max_temp",
|
|
160
|
-
}
|
|
161
|
-
|
|
162
130
|
# Mapping from circuit number to section names
|
|
163
131
|
CIRCUIT_HEATING_SECTIONS: Final[dict[int, str]] = {
|
|
164
132
|
1: "heating",
|
|
165
133
|
2: "heating_circuit2",
|
|
166
|
-
3: "heating_circuit3",
|
|
167
134
|
}
|
|
168
135
|
|
|
169
136
|
CIRCUIT_STATIC_SECTIONS: Final[dict[int, str]] = {
|
|
170
137
|
1: "staticValues",
|
|
171
138
|
2: "staticValues_circuit2",
|
|
172
|
-
3: "staticValues_circuit3",
|
|
173
139
|
}
|
|
174
140
|
|
|
175
141
|
# Mapping from circuit number to thermostat parameter IDs
|
|
176
142
|
CIRCUIT_THERMOSTAT_PARAMS: Final[dict[int, dict[str, str]]] = {
|
|
177
143
|
1: {"target_temperature": "710", "hvac_mode": "700"},
|
|
178
144
|
2: {"target_temperature": "1010", "hvac_mode": "1000"},
|
|
179
|
-
3: {"target_temperature": "1310", "hvac_mode": "1300"},
|
|
180
145
|
}
|
|
181
146
|
|
|
182
147
|
# Parameter IDs used to probe whether a heating circuit exists on the device.
|
|
@@ -184,7 +149,6 @@ CIRCUIT_THERMOSTAT_PARAMS: Final[dict[int, dict[str, str]]] = {
|
|
|
184
149
|
CIRCUIT_PROBE_PARAMS: Final[dict[int, str]] = {
|
|
185
150
|
1: "700",
|
|
186
151
|
2: "1000",
|
|
187
|
-
3: "1300",
|
|
188
152
|
}
|
|
189
153
|
|
|
190
154
|
# Status parameter IDs used as a secondary check for circuit availability.
|
|
@@ -192,7 +156,6 @@ CIRCUIT_PROBE_PARAMS: Final[dict[int, str]] = {
|
|
|
192
156
|
CIRCUIT_STATUS_PARAMS: Final[dict[int, str]] = {
|
|
193
157
|
1: "8000",
|
|
194
158
|
2: "8001",
|
|
195
|
-
3: "8002",
|
|
196
159
|
}
|
|
197
160
|
|
|
198
161
|
# Marker value returned by BSB-LAN for parameters on inactive circuits
|
|
@@ -217,9 +180,7 @@ def build_api_config(version: str) -> APIConfig:
|
|
|
217
180
|
"hot_water": BASE_HOT_WATER_PARAMS.copy(),
|
|
218
181
|
# Multi-circuit sections
|
|
219
182
|
"heating_circuit2": BASE_HEATING_CIRCUIT2_PARAMS.copy(),
|
|
220
|
-
"heating_circuit3": BASE_HEATING_CIRCUIT3_PARAMS.copy(),
|
|
221
183
|
"staticValues_circuit2": BASE_STATIC_VALUES_CIRCUIT2_PARAMS.copy(),
|
|
222
|
-
"staticValues_circuit3": BASE_STATIC_VALUES_CIRCUIT3_PARAMS.copy(),
|
|
223
184
|
}
|
|
224
185
|
|
|
225
186
|
if version == "v1":
|
|
@@ -227,9 +188,6 @@ def build_api_config(version: str) -> APIConfig:
|
|
|
227
188
|
config["staticValues_circuit2"].update(
|
|
228
189
|
V1_STATIC_VALUES_CIRCUIT2_EXTENSIONS,
|
|
229
190
|
)
|
|
230
|
-
config["staticValues_circuit3"].update(
|
|
231
|
-
V1_STATIC_VALUES_CIRCUIT3_EXTENSIONS,
|
|
232
|
-
)
|
|
233
191
|
elif version == "v3":
|
|
234
192
|
config["heating"].update(V3_HEATING_EXTENSIONS)
|
|
235
193
|
config["staticValues"].update(V3_STATIC_VALUES_EXTENSIONS)
|
|
@@ -237,10 +195,6 @@ def build_api_config(version: str) -> APIConfig:
|
|
|
237
195
|
config["staticValues_circuit2"].update(
|
|
238
196
|
V3_STATIC_VALUES_CIRCUIT2_EXTENSIONS,
|
|
239
197
|
)
|
|
240
|
-
config["heating_circuit3"].update(V3_HEATING_CIRCUIT3_EXTENSIONS)
|
|
241
|
-
config["staticValues_circuit3"].update(
|
|
242
|
-
V3_STATIC_VALUES_CIRCUIT3_EXTENSIONS,
|
|
243
|
-
)
|
|
244
198
|
|
|
245
199
|
return config
|
|
246
200
|
|
|
@@ -520,9 +474,7 @@ SESSION_NOT_INITIALIZED_ERROR_MSG: Final[str] = "Session not initialized"
|
|
|
520
474
|
API_DATA_NOT_INITIALIZED_ERROR_MSG: Final[str] = "API data not initialized"
|
|
521
475
|
API_VALIDATOR_NOT_INITIALIZED_ERROR_MSG: Final[str] = "API validator not initialized"
|
|
522
476
|
SECTION_NOT_FOUND_ERROR_MSG: Final[str] = "Section '{}' not found in API data"
|
|
523
|
-
INVALID_CIRCUIT_ERROR_MSG: Final[str] =
|
|
524
|
-
"Invalid circuit number: {}. Must be 1, 2, or 3."
|
|
525
|
-
)
|
|
477
|
+
INVALID_CIRCUIT_ERROR_MSG: Final[str] = "Invalid circuit number: {}. Must be 1 or 2."
|
|
526
478
|
INVALID_RESPONSE_ERROR_MSG: Final[str] = (
|
|
527
479
|
"Invalid response format from BSB-LAN device: {}"
|
|
528
480
|
)
|
|
@@ -453,7 +453,6 @@ class State(BaseModel):
|
|
|
453
453
|
hvac_action: EntityInfo[int] | None = None
|
|
454
454
|
hvac_mode_changeover: EntityInfo[int] | None = None
|
|
455
455
|
current_temperature: EntityInfo[float] | None = None
|
|
456
|
-
room1_thermostat_mode: EntityInfo[int] | None = None
|
|
457
456
|
room1_temp_setpoint_boost: EntityInfo[float] | None = None
|
|
458
457
|
|
|
459
458
|
|
|
@@ -61,18 +61,6 @@
|
|
|
61
61
|
"readwrite": 1,
|
|
62
62
|
"unit": "°C"
|
|
63
63
|
},
|
|
64
|
-
"8749": {
|
|
65
|
-
"name": "Room thermostat heating circuit 1",
|
|
66
|
-
"dataType_name": "ENUM",
|
|
67
|
-
"dataType_family": "ENUM",
|
|
68
|
-
"error": 0,
|
|
69
|
-
"value": "0",
|
|
70
|
-
"desc": "No demand",
|
|
71
|
-
"dataType": 1,
|
|
72
|
-
"readonly": 1,
|
|
73
|
-
"readwrite": 1,
|
|
74
|
-
"unit": ""
|
|
75
|
-
},
|
|
76
64
|
"770": {
|
|
77
65
|
"name": "Room temp setpoint boost (boost heating)",
|
|
78
66
|
"dataType_name": "TEMP",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
"readwrite": 1,
|
|
49
49
|
"unit": ""
|
|
50
50
|
},
|
|
51
|
-
"
|
|
52
|
-
"name": "Room temperature
|
|
51
|
+
"8770": {
|
|
52
|
+
"name": "Room temperature actual value 2",
|
|
53
53
|
"dataType_name": "TEMP",
|
|
54
54
|
"dataType_family": "VALS",
|
|
55
55
|
"error": 0,
|
|
@@ -61,18 +61,6 @@
|
|
|
61
61
|
"readwrite": 1,
|
|
62
62
|
"unit": "°C"
|
|
63
63
|
},
|
|
64
|
-
"8750": {
|
|
65
|
-
"name": "Room thermostat heating circuit 2",
|
|
66
|
-
"dataType_name": "ENUM",
|
|
67
|
-
"dataType_family": "ENUM",
|
|
68
|
-
"error": 0,
|
|
69
|
-
"value": "0",
|
|
70
|
-
"desc": "No demand",
|
|
71
|
-
"dataType": 1,
|
|
72
|
-
"readonly": 1,
|
|
73
|
-
"readwrite": 1,
|
|
74
|
-
"unit": ""
|
|
75
|
-
},
|
|
76
64
|
"1070": {
|
|
77
65
|
"name": "Room temp setpoint boost (boost heating)",
|
|
78
66
|
"dataType_name": "TEMP",
|
|
@@ -372,9 +372,7 @@ async def test_validate_api_section_hot_water_cache() -> None:
|
|
|
372
372
|
"device": {},
|
|
373
373
|
"hot_water": {"1600": "operating_mode", "1610": "nominal_setpoint"},
|
|
374
374
|
"heating_circuit2": {},
|
|
375
|
-
"heating_circuit3": {},
|
|
376
375
|
"staticValues_circuit2": {},
|
|
377
|
-
"staticValues_circuit3": {},
|
|
378
376
|
}
|
|
379
377
|
bsblan._api_validator = APIValidator(bsblan._api_data)
|
|
380
378
|
|