python-bsblan 3.1.1__tar.gz → 3.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-3.1.3/.github/copilot-instructions.md +205 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/codeql.yaml +3 -3
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/labels.yaml +1 -1
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/linting.yaml +7 -7
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/release.yaml +3 -3
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/tests.yaml +4 -4
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/typing.yaml +2 -2
- python_bsblan-3.1.3/.nvmrc +1 -0
- python_bsblan-3.1.3/AGENTS.md +1 -0
- python_bsblan-3.1.3/CLAUDE.md +1 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/PKG-INFO +4 -3
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/examples/control.py +6 -5
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/pyproject.toml +11 -10
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/src/bsblan/__init__.py +8 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/src/bsblan/bsblan.py +245 -371
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/src/bsblan/constants.py +39 -46
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/src/bsblan/models.py +231 -7
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/src/bsblan/utility.py +60 -1
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_bsblan_edge_cases.py +33 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_dhw_time_switch.py +18 -28
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_info.py +10 -0
- python_bsblan-3.1.3/tests/test_schedule_models.py +229 -0
- python_bsblan-3.1.3/tests/test_set_hot_water_schedule.py +174 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_set_hotwater.py +50 -72
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_state.py +1 -1
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_thermostat.py +37 -3
- python_bsblan-3.1.3/tests/test_utility.py +387 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/uv.lock +338 -623
- python_bsblan-3.1.1/.nvmrc +0 -1
- python_bsblan-3.1.1/tests/test_utility.py +0 -162
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.editorconfig +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.gitattributes +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/CODE_OF_CONDUCT.md +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/CONTRIBUTING.md +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/ISSUE_TEMPLATE/PULL_REQUEST_TEMPLATE.md +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/LICENSE.md +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/labels.yml +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/release-drafter.yml +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/renovate.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/lock.yaml +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/pr-labels.yaml +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/release-drafter.yaml +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.github/workflows/stale.yaml +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.gitignore +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.pre-commit-config.yaml +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.prettierignore +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/.yamllint +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/README.md +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/examples/ruff.toml +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/package-lock.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/package.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/sonar-project.properties +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/src/bsblan/exceptions.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/src/bsblan/py.typed +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/__init__.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/conftest.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/device.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/dict_version.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/hot_water_state.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/info.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/password.txt +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/sensor.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/state.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/static_state.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/thermostat_hvac.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/thermostat_temp.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/fixtures/time.json +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/ruff.toml +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_api_initialization.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_api_validation.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_auth.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_bsblan.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_configuration.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_constants.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_context_manager.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_device.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_entity_info.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_hot_water_additional.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_hotwater_state.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_initialization.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_reset_validation.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_sensor.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_static_state.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_temperature_unit.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_temperature_validation.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_time.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_utility_additional.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_utility_edge_cases.py +0 -0
- {python_bsblan-3.1.1 → python_bsblan-3.1.3}/tests/test_version_errors.py +0 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# GitHub Copilot Instructions for python-bsblan
|
|
2
|
+
|
|
3
|
+
This repository contains the `python-bsblan` library, an asynchronous Python client for BSB-LAN devices (heating controllers).
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
- **Language**: Python 3.12+
|
|
8
|
+
- **Type**: Async library using `aiohttp`
|
|
9
|
+
- **Purpose**: Communicate with BSB-LAN devices to read/write heating parameters
|
|
10
|
+
- **License**: MIT
|
|
11
|
+
|
|
12
|
+
## Code Quality Standards
|
|
13
|
+
|
|
14
|
+
### Required Before Committing
|
|
15
|
+
|
|
16
|
+
Always run these commands after making changes:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Run all pre-commit hooks (ruff, mypy, pylint, pytest)
|
|
20
|
+
uv run pre-commit run --all-files
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Pre-commit Includes
|
|
24
|
+
- **Ruff**: Linting and formatting (88 char line limit)
|
|
25
|
+
- **MyPy**: Static type checking
|
|
26
|
+
- **Pylint**: Code analysis
|
|
27
|
+
- **Pytest**: Test execution with coverage
|
|
28
|
+
|
|
29
|
+
### Coverage Requirements
|
|
30
|
+
- Maintain **95%+ total test coverage**
|
|
31
|
+
- **Patch coverage must be 100%** - all new/modified code must be fully tested
|
|
32
|
+
- GitHub Actions will fail if patch coverage is below 100%
|
|
33
|
+
- Run coverage check: `uv run pytest --cov=src/bsblan --cov-report=term-missing`
|
|
34
|
+
|
|
35
|
+
## Project Structure
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
src/bsblan/
|
|
39
|
+
├── __init__.py # Package exports
|
|
40
|
+
├── bsblan.py # Main BSBLAN client class
|
|
41
|
+
├── constants.py # Parameter IDs and mappings
|
|
42
|
+
├── models.py # Dataclass models for API responses
|
|
43
|
+
├── utility.py # Helper utilities
|
|
44
|
+
├── exceptions.py # Custom exceptions
|
|
45
|
+
└── py.typed # PEP-561 marker
|
|
46
|
+
|
|
47
|
+
tests/
|
|
48
|
+
├── conftest.py # Pytest fixtures
|
|
49
|
+
├── fixtures/ # JSON test data
|
|
50
|
+
└── test_*.py # Test files
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Parameter Naming Conventions
|
|
54
|
+
|
|
55
|
+
### BSB-LAN Parameters
|
|
56
|
+
Parameters are identified by numeric IDs and mapped to readable names in `constants.py`.
|
|
57
|
+
|
|
58
|
+
**Naming Rules:**
|
|
59
|
+
- Use `snake_case` for all parameter names
|
|
60
|
+
- Group related parameters with common prefixes
|
|
61
|
+
- Legionella-related parameters use `legionella_function_*` prefix:
|
|
62
|
+
- `legionella_function_setpoint` (ID: 1645)
|
|
63
|
+
- `legionella_function_periodicity` (ID: 1641)
|
|
64
|
+
- `legionella_function_day` (ID: 1642)
|
|
65
|
+
- `legionella_function_time` (ID: 1644)
|
|
66
|
+
- `legionella_function_dwelling_time` (ID: 1646)
|
|
67
|
+
- DHW (Domestic Hot Water) parameters use `dhw_*` prefix
|
|
68
|
+
|
|
69
|
+
### Adding New Parameters
|
|
70
|
+
|
|
71
|
+
1. **Add to `constants.py`**:
|
|
72
|
+
```python
|
|
73
|
+
BASE_HOT_WATER_PARAMS: Final[dict[str, str]] = {
|
|
74
|
+
"1645": "legionella_function_setpoint", # Parameter ID: name
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
2. **Add to model in `models.py`**:
|
|
79
|
+
```python
|
|
80
|
+
@dataclass
|
|
81
|
+
class HotWaterConfig(DataClassORJSONMixin):
|
|
82
|
+
legionella_function_setpoint: ParameterValue | None = None
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
3. **Update method in `bsblan.py`** if the parameter is settable:
|
|
86
|
+
```python
|
|
87
|
+
async def set_hot_water(
|
|
88
|
+
self,
|
|
89
|
+
legionella_function_setpoint: float | None = None,
|
|
90
|
+
) -> None:
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
4. **Add tests in `tests/test_*.py`**
|
|
94
|
+
|
|
95
|
+
## Polling Categories
|
|
96
|
+
|
|
97
|
+
Parameters are organized into polling categories based on how frequently they change:
|
|
98
|
+
|
|
99
|
+
### Fast Poll (State - every update)
|
|
100
|
+
- Current temperatures
|
|
101
|
+
- HVAC action/state
|
|
102
|
+
- Pump states
|
|
103
|
+
|
|
104
|
+
### Slow Poll (Config - every 5 minutes)
|
|
105
|
+
- Operating modes
|
|
106
|
+
- Setpoints
|
|
107
|
+
- Legionella function settings
|
|
108
|
+
- Time programs
|
|
109
|
+
|
|
110
|
+
### Static (rarely changes)
|
|
111
|
+
- Device identification
|
|
112
|
+
- Min/max temperature limits
|
|
113
|
+
|
|
114
|
+
## Data Models
|
|
115
|
+
|
|
116
|
+
### Model Pattern
|
|
117
|
+
All models use `mashumaro` for JSON serialization:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from dataclasses import dataclass
|
|
121
|
+
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
|
122
|
+
|
|
123
|
+
@dataclass
|
|
124
|
+
class HotWaterConfig(DataClassORJSONMixin):
|
|
125
|
+
"""Hot water configuration parameters."""
|
|
126
|
+
operating_mode: ParameterValue | None = None
|
|
127
|
+
nominal_setpoint: ParameterValue | None = None
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### ParameterValue Structure
|
|
131
|
+
Each parameter returns a `ParameterValue` with:
|
|
132
|
+
- `value`: The actual value
|
|
133
|
+
- `unit`: Unit of measurement
|
|
134
|
+
- `desc`: Human-readable description
|
|
135
|
+
- `dataType`: Data type information
|
|
136
|
+
|
|
137
|
+
## Async Patterns
|
|
138
|
+
|
|
139
|
+
### Client Usage
|
|
140
|
+
```python
|
|
141
|
+
async with BSBLAN(host="192.168.1.100") as client:
|
|
142
|
+
state = await client.state()
|
|
143
|
+
await client.set_hot_water(nominal_setpoint=55.0)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Error Handling
|
|
147
|
+
- Use `BSBLANError` for general errors
|
|
148
|
+
- Use `BSBLANConnectionError` for connection issues
|
|
149
|
+
- Always validate only one parameter is set per API call
|
|
150
|
+
|
|
151
|
+
## Testing Patterns
|
|
152
|
+
|
|
153
|
+
### Test Structure
|
|
154
|
+
```python
|
|
155
|
+
@pytest.mark.asyncio
|
|
156
|
+
async def test_set_hot_water(mock_bsblan: BSBLAN) -> None:
|
|
157
|
+
"""Test setting BSBLAN hot water state."""
|
|
158
|
+
await mock_bsblan.set_hot_water(nominal_setpoint=60.0)
|
|
159
|
+
mock_bsblan._request.assert_awaited_with(
|
|
160
|
+
base_path="/JS",
|
|
161
|
+
data={"Parameter": "1610", "Value": "60.0", "Type": "1"},
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Fixtures Location
|
|
166
|
+
Test fixtures (JSON responses) are in `tests/fixtures/`
|
|
167
|
+
|
|
168
|
+
## Common Tasks
|
|
169
|
+
|
|
170
|
+
### Adding a New Settable Parameter
|
|
171
|
+
|
|
172
|
+
1. Add parameter ID mapping in `constants.py`
|
|
173
|
+
2. Add field to appropriate model in `models.py`
|
|
174
|
+
3. Add parameter to method signature in `bsblan.py`
|
|
175
|
+
4. Update docstring with parameter description
|
|
176
|
+
5. Add state preparation logic in `_prepare_*_state()` method
|
|
177
|
+
6. Add tests for the new parameter
|
|
178
|
+
7. Run `uv run pre-commit run --all-files`
|
|
179
|
+
|
|
180
|
+
### Renaming a Parameter
|
|
181
|
+
|
|
182
|
+
When renaming parameters for consistency:
|
|
183
|
+
1. Update `constants.py` - parameter mapping
|
|
184
|
+
2. Update `models.py` - dataclass field
|
|
185
|
+
3. Update `bsblan.py` - method parameters and state handling
|
|
186
|
+
4. Update `tests/` - all test files using the parameter
|
|
187
|
+
5. Update `examples/` - any example code
|
|
188
|
+
6. Run `uv run pre-commit run --all-files`
|
|
189
|
+
|
|
190
|
+
## API Versions
|
|
191
|
+
|
|
192
|
+
The library supports BSB-LAN API versions:
|
|
193
|
+
- **v1**: Original API
|
|
194
|
+
- **v3**: Extended API with additional parameters
|
|
195
|
+
|
|
196
|
+
Version-specific parameters are handled in `constants.py` with extension dictionaries.
|
|
197
|
+
|
|
198
|
+
## Don't Forget
|
|
199
|
+
|
|
200
|
+
- ✅ Run `uv run pre-commit run --all-files` after every change
|
|
201
|
+
- ✅ Maintain 95%+ test coverage
|
|
202
|
+
- ✅ Use type hints on all functions
|
|
203
|
+
- ✅ Add docstrings to public methods
|
|
204
|
+
- ✅ Keep line length under 88 characters
|
|
205
|
+
- ✅ Use consistent parameter naming (check existing patterns)
|
|
@@ -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@v5.0.
|
|
20
|
+
uses: actions/checkout@v5.0.1
|
|
21
21
|
- name: 🏗 Initialize CodeQL
|
|
22
|
-
uses: github/codeql-action/init@v3.
|
|
22
|
+
uses: github/codeql-action/init@v3.31.6
|
|
23
23
|
- name: 🚀 Perform CodeQL Analysis
|
|
24
|
-
uses: github/codeql-action/analyze@v3.
|
|
24
|
+
uses: github/codeql-action/analyze@v3.31.6
|
|
@@ -8,7 +8,7 @@ on:
|
|
|
8
8
|
workflow_dispatch:
|
|
9
9
|
|
|
10
10
|
env:
|
|
11
|
-
DEFAULT_PYTHON: "3.
|
|
11
|
+
DEFAULT_PYTHON: "3.13"
|
|
12
12
|
|
|
13
13
|
jobs:
|
|
14
14
|
codespell:
|
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
runs-on: ubuntu-latest
|
|
17
17
|
steps:
|
|
18
18
|
- name: ⤵️ Check out code from GitHub
|
|
19
|
-
uses: actions/checkout@v5.0.
|
|
19
|
+
uses: actions/checkout@v5.0.1
|
|
20
20
|
- name: 🏗 Set up uv
|
|
21
21
|
uses: astral-sh/setup-uv@v6
|
|
22
22
|
with:
|
|
@@ -36,7 +36,7 @@ jobs:
|
|
|
36
36
|
runs-on: ubuntu-latest
|
|
37
37
|
steps:
|
|
38
38
|
- name: ⤵️ Check out code from GitHub
|
|
39
|
-
uses: actions/checkout@v5.0.
|
|
39
|
+
uses: actions/checkout@v5.0.1
|
|
40
40
|
- name: 🏗 Set up uv
|
|
41
41
|
uses: astral-sh/setup-uv@v6
|
|
42
42
|
with:
|
|
@@ -58,7 +58,7 @@ jobs:
|
|
|
58
58
|
runs-on: ubuntu-latest
|
|
59
59
|
steps:
|
|
60
60
|
- name: ⤵️ Check out code from GitHub
|
|
61
|
-
uses: actions/checkout@v5.0.
|
|
61
|
+
uses: actions/checkout@v5.0.1
|
|
62
62
|
- name: 🏗 Set up uv
|
|
63
63
|
uses: astral-sh/setup-uv@v6
|
|
64
64
|
with:
|
|
@@ -102,7 +102,7 @@ jobs:
|
|
|
102
102
|
runs-on: ubuntu-latest
|
|
103
103
|
steps:
|
|
104
104
|
- name: ⤵️ Check out code from GitHub
|
|
105
|
-
uses: actions/checkout@v5.0.
|
|
105
|
+
uses: actions/checkout@v5.0.1
|
|
106
106
|
- name: 🏗 Set up uv
|
|
107
107
|
uses: astral-sh/setup-uv@v6
|
|
108
108
|
with:
|
|
@@ -122,7 +122,7 @@ jobs:
|
|
|
122
122
|
runs-on: ubuntu-latest
|
|
123
123
|
steps:
|
|
124
124
|
- name: ⤵️ Check out code from GitHub
|
|
125
|
-
uses: actions/checkout@v5.0.
|
|
125
|
+
uses: actions/checkout@v5.0.1
|
|
126
126
|
- name: 🏗 Set up uv
|
|
127
127
|
uses: astral-sh/setup-uv@v6
|
|
128
128
|
with:
|
|
@@ -142,7 +142,7 @@ jobs:
|
|
|
142
142
|
runs-on: ubuntu-latest
|
|
143
143
|
steps:
|
|
144
144
|
- name: ⤵️ Check out code from GitHub
|
|
145
|
-
uses: actions/checkout@v5.0.
|
|
145
|
+
uses: actions/checkout@v5.0.1
|
|
146
146
|
- name: 🏗 Set up uv
|
|
147
147
|
uses: astral-sh/setup-uv@v6
|
|
148
148
|
with:
|
|
@@ -8,7 +8,7 @@ on:
|
|
|
8
8
|
- published
|
|
9
9
|
|
|
10
10
|
env:
|
|
11
|
-
DEFAULT_PYTHON: "3.
|
|
11
|
+
DEFAULT_PYTHON: "3.13"
|
|
12
12
|
|
|
13
13
|
jobs:
|
|
14
14
|
release:
|
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
id-token: write
|
|
23
23
|
steps:
|
|
24
24
|
- name: ⤵️ Check out code from GitHub
|
|
25
|
-
uses: actions/checkout@v5.0.
|
|
25
|
+
uses: actions/checkout@v5.0.1
|
|
26
26
|
- name: 🏗 Set up uv
|
|
27
27
|
uses: astral-sh/setup-uv@v6
|
|
28
28
|
with:
|
|
@@ -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.1.0
|
|
52
52
|
with:
|
|
53
53
|
inputs: ./dist/*.tar.gz ./dist/*.whl
|
|
54
54
|
release-signing-artifacts: false
|
|
@@ -8,7 +8,7 @@ on:
|
|
|
8
8
|
workflow_dispatch:
|
|
9
9
|
|
|
10
10
|
env:
|
|
11
|
-
DEFAULT_PYTHON: "3.
|
|
11
|
+
DEFAULT_PYTHON: "3.13"
|
|
12
12
|
|
|
13
13
|
jobs:
|
|
14
14
|
pytest:
|
|
@@ -16,10 +16,10 @@ jobs:
|
|
|
16
16
|
runs-on: ubuntu-latest
|
|
17
17
|
strategy:
|
|
18
18
|
matrix:
|
|
19
|
-
python: ["3.
|
|
19
|
+
python: ["3.12", "3.13", "3.14"]
|
|
20
20
|
steps:
|
|
21
21
|
- name: ⤵️ Check out code from GitHub
|
|
22
|
-
uses: actions/checkout@v5.0.
|
|
22
|
+
uses: actions/checkout@v5.0.1
|
|
23
23
|
- name: 🏗 Set up uv
|
|
24
24
|
uses: astral-sh/setup-uv@v6
|
|
25
25
|
with:
|
|
@@ -45,7 +45,7 @@ jobs:
|
|
|
45
45
|
needs: pytest
|
|
46
46
|
steps:
|
|
47
47
|
- name: ⤵️ Check out code from GitHub
|
|
48
|
-
uses: actions/checkout@v5.0.
|
|
48
|
+
uses: actions/checkout@v5.0.1
|
|
49
49
|
with:
|
|
50
50
|
fetch-depth: 0
|
|
51
51
|
- name: ⬇️ Download coverage data
|
|
@@ -8,7 +8,7 @@ on:
|
|
|
8
8
|
workflow_dispatch:
|
|
9
9
|
|
|
10
10
|
env:
|
|
11
|
-
DEFAULT_PYTHON: "3.
|
|
11
|
+
DEFAULT_PYTHON: "3.13"
|
|
12
12
|
|
|
13
13
|
jobs:
|
|
14
14
|
mypy:
|
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
runs-on: ubuntu-latest
|
|
17
17
|
steps:
|
|
18
18
|
- name: ⤵️ Check out code from GitHub
|
|
19
|
-
uses: actions/checkout@v5.0.
|
|
19
|
+
uses: actions/checkout@v5.0.1
|
|
20
20
|
- name: 🏗 Set up uv
|
|
21
21
|
uses: astral-sh/setup-uv@v6
|
|
22
22
|
with:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22.21.1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.github/copilot-instructions.md
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.github/copilot-instructions.md
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-bsblan
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.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
|
|
@@ -17,10 +17,11 @@ Classifier: Intended Audience :: Developers
|
|
|
17
17
|
Classifier: License :: OSI Approved :: MIT License
|
|
18
18
|
Classifier: Natural Language :: English
|
|
19
19
|
Classifier: Programming Language :: Python :: 3
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
-
Requires-Python: >=3.
|
|
24
|
+
Requires-Python: >=3.12
|
|
24
25
|
Requires-Dist: aiohttp>=3.8.1
|
|
25
26
|
Requires-Dist: backoff>=2.2.1
|
|
26
27
|
Requires-Dist: mashumaro>=3.13.1
|
|
@@ -26,6 +26,7 @@ from bsblan import (
|
|
|
26
26
|
HotWaterState,
|
|
27
27
|
Info,
|
|
28
28
|
Sensor,
|
|
29
|
+
SetHotWaterParam,
|
|
29
30
|
State,
|
|
30
31
|
StaticState,
|
|
31
32
|
)
|
|
@@ -199,10 +200,10 @@ async def print_hot_water_config(hot_water_config: HotWaterConfig) -> None:
|
|
|
199
200
|
hot_water_config.legionella_function, "desc", "N/A"
|
|
200
201
|
),
|
|
201
202
|
"Legionella Setpoint": await get_attribute(
|
|
202
|
-
hot_water_config.
|
|
203
|
+
hot_water_config.legionella_function_setpoint, "value", "N/A"
|
|
203
204
|
),
|
|
204
205
|
"Legionella Periodicity": await get_attribute(
|
|
205
|
-
hot_water_config.
|
|
206
|
+
hot_water_config.legionella_function_periodicity, "value", "N/A"
|
|
206
207
|
),
|
|
207
208
|
"Circulation Pump Release": await get_attribute(
|
|
208
209
|
hot_water_config.dhw_circulation_pump_release, "desc", "N/A"
|
|
@@ -271,9 +272,9 @@ async def main() -> None:
|
|
|
271
272
|
print("\nSetting temperature to 18°C")
|
|
272
273
|
await bsblan.thermostat(target_temperature="18")
|
|
273
274
|
|
|
274
|
-
# Set HVAC mode
|
|
275
|
+
# Set HVAC mode (using raw integer: 0=off, 1=auto, 2=eco, 3=heat)
|
|
275
276
|
print("Setting HVAC mode to heat")
|
|
276
|
-
await bsblan.thermostat(hvac_mode=
|
|
277
|
+
await bsblan.thermostat(hvac_mode=3) # 3 = heat
|
|
277
278
|
|
|
278
279
|
# Get and print sensor information
|
|
279
280
|
sensor: Sensor = await bsblan.sensor()
|
|
@@ -316,7 +317,7 @@ async def main() -> None:
|
|
|
316
317
|
dhw_programs = DHWTimeSwitchPrograms(
|
|
317
318
|
monday="13:00-14:00 ##:##-##:## ##:##-##:##"
|
|
318
319
|
)
|
|
319
|
-
await bsblan.set_hot_water(dhw_time_programs=dhw_programs)
|
|
320
|
+
await bsblan.set_hot_water(SetHotWaterParam(dhw_time_programs=dhw_programs))
|
|
320
321
|
|
|
321
322
|
# Example: Set device time
|
|
322
323
|
print("\nSetting device time to current system time")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-bsblan"
|
|
3
|
-
version = "3.1.
|
|
3
|
+
version = "3.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"}
|
|
@@ -17,12 +17,13 @@ classifiers = [
|
|
|
17
17
|
"Framework :: AsyncIO",
|
|
18
18
|
"Intended Audience :: Developers",
|
|
19
19
|
"Natural Language :: English",
|
|
20
|
-
"Programming Language :: Python :: 3.11",
|
|
21
20
|
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
22
23
|
"Programming Language :: Python :: 3",
|
|
23
24
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
25
|
]
|
|
25
|
-
requires-python = ">=3.
|
|
26
|
+
requires-python = ">=3.12"
|
|
26
27
|
dependencies = [
|
|
27
28
|
"aiohttp>=3.8.1",
|
|
28
29
|
"yarl>=1.7.2",
|
|
@@ -176,28 +177,28 @@ build-backend = "hatchling.build"
|
|
|
176
177
|
[dependency-groups]
|
|
177
178
|
dev = [
|
|
178
179
|
"aresponses==3.0.0",
|
|
179
|
-
"bandit==1.
|
|
180
|
+
"bandit==1.9.2",
|
|
180
181
|
"black==25.11.0",
|
|
181
182
|
"blacken-docs==1.20.0",
|
|
182
183
|
"codespell==2.4.1",
|
|
183
184
|
"covdefaults==2.3.0",
|
|
184
|
-
"coverage==7.
|
|
185
|
+
"coverage==7.12.0",
|
|
185
186
|
"darglint==1.8.1",
|
|
186
187
|
"flake8==7.3.0",
|
|
187
188
|
"flake8-simplify==0.22.0",
|
|
188
189
|
# hatch is required to support type hinting and proper packaging of the py.typed file.
|
|
189
190
|
"hatch>=1.14.1",
|
|
190
|
-
"isort==6.0
|
|
191
|
+
"isort==6.1.0",
|
|
191
192
|
"mypy==1.18.2",
|
|
192
|
-
"pre-commit==4.
|
|
193
|
+
"pre-commit==4.5.0",
|
|
193
194
|
"pre-commit-hooks==6.0.0",
|
|
194
195
|
"pylint==3.3.9",
|
|
195
196
|
"pytest>=8.3.5",
|
|
196
197
|
"pytest-asyncio==1.3.0",
|
|
197
198
|
"pytest-cov==7.0.0",
|
|
198
|
-
"pyupgrade==3.
|
|
199
|
-
"ruff==0.14.
|
|
200
|
-
"safety==3.
|
|
199
|
+
"pyupgrade==3.21.2",
|
|
200
|
+
"ruff==0.14.6",
|
|
201
|
+
"safety==3.7.0",
|
|
201
202
|
"vulture==2.14",
|
|
202
203
|
"yamllint==1.37.1",
|
|
203
204
|
]
|
|
@@ -3,16 +3,20 @@
|
|
|
3
3
|
from .bsblan import BSBLAN, BSBLANConfig
|
|
4
4
|
from .exceptions import BSBLANAuthError, BSBLANConnectionError, BSBLANError
|
|
5
5
|
from .models import (
|
|
6
|
+
DaySchedule,
|
|
6
7
|
Device,
|
|
7
8
|
DeviceTime,
|
|
9
|
+
DHWSchedule,
|
|
8
10
|
DHWTimeSwitchPrograms,
|
|
9
11
|
HotWaterConfig,
|
|
10
12
|
HotWaterSchedule,
|
|
11
13
|
HotWaterState,
|
|
12
14
|
Info,
|
|
13
15
|
Sensor,
|
|
16
|
+
SetHotWaterParam,
|
|
14
17
|
State,
|
|
15
18
|
StaticState,
|
|
19
|
+
TimeSlot,
|
|
16
20
|
)
|
|
17
21
|
|
|
18
22
|
__all__ = [
|
|
@@ -21,7 +25,9 @@ __all__ = [
|
|
|
21
25
|
"BSBLANConfig",
|
|
22
26
|
"BSBLANConnectionError",
|
|
23
27
|
"BSBLANError",
|
|
28
|
+
"DHWSchedule",
|
|
24
29
|
"DHWTimeSwitchPrograms",
|
|
30
|
+
"DaySchedule",
|
|
25
31
|
"Device",
|
|
26
32
|
"DeviceTime",
|
|
27
33
|
"HotWaterConfig",
|
|
@@ -29,6 +35,8 @@ __all__ = [
|
|
|
29
35
|
"HotWaterState",
|
|
30
36
|
"Info",
|
|
31
37
|
"Sensor",
|
|
38
|
+
"SetHotWaterParam",
|
|
32
39
|
"State",
|
|
33
40
|
"StaticState",
|
|
41
|
+
"TimeSlot",
|
|
34
42
|
]
|