python-bsblan 4.1.0b2__tar.gz → 4.2.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-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/codeql.yaml +8 -3
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/labels.yaml +5 -1
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/linting.yaml +16 -13
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/lock.yaml +4 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/pr-labels.yaml +3 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/release-drafter.yaml +6 -1
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/release.yaml +2 -2
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/stale.yaml +4 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/tests.yaml +9 -4
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/typing.yaml +2 -2
- python_bsblan-4.2.0/.nvmrc +1 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/PKG-INFO +1 -1
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/examples/control.py +2 -2
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/package-lock.json +4 -4
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/package.json +1 -1
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/pyproject.toml +7 -7
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/src/bsblan/__init__.py +4 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/src/bsblan/constants.py +71 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/src/bsblan/models.py +48 -1
- python_bsblan-4.2.0/tests/test_entity_info_ha.py +220 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/uv.lock +532 -498
- python_bsblan-4.1.0b2/.nvmrc +0 -1
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.editorconfig +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.gitattributes +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/CODE_OF_CONDUCT.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/CONTRIBUTING.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/ISSUE_TEMPLATE/PULL_REQUEST_TEMPLATE.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/copilot-instructions.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/labels.yml +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/prompts/add-parameter.prompt.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/prompts/code-review.prompt.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/release-drafter.yml +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/renovate.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/skills/bsblan-parameters/SKILL.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/skills/bsblan-testing/SKILL.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.github/workflows/auto-approve-renovate.yml +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.gitignore +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.pre-commit-config.yaml +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.prettierignore +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/.yamllint +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/AGENTS.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/CLAUDE.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/LICENSE.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/README.md +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/examples/discovery.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/examples/profile_init.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/examples/ruff.toml +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/examples/speed_test.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/sonar-project.properties +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/src/bsblan/bsblan.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/src/bsblan/exceptions.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/src/bsblan/py.typed +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/src/bsblan/utility.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/__init__.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/conftest.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/device.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/dict_version.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/hot_water_state.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/info.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/password.txt +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/sensor.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/state.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/static_state.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/thermostat_hvac.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/thermostat_temp.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/fixtures/time.json +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/ruff.toml +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_api_initialization.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_api_validation.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_auth.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_backoff_retry.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_bsblan.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_bsblan_edge_cases.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_configuration.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_constants.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_context_manager.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_device.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_dhw_time_switch.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_entity_info.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_hot_water_additional.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_hotwater_state.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_include_parameter.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_info.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_initialization.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_read_parameters.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_reset_validation.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_schedule_models.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_sensor.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_set_hot_water_schedule.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_set_hotwater.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_state.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_static_state.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_temperature_unit.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_temperature_validation.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_thermostat.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_time.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_utility.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_utility_additional.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_utility_edge_cases.py +0 -0
- {python_bsblan-4.1.0b2 → python_bsblan-4.2.0}/tests/test_version_errors.py +0 -0
|
@@ -11,14 +11,19 @@ on:
|
|
|
11
11
|
schedule:
|
|
12
12
|
- cron: "30 1 * * 0"
|
|
13
13
|
|
|
14
|
+
permissions:
|
|
15
|
+
actions: read
|
|
16
|
+
contents: read
|
|
17
|
+
security-events: write
|
|
18
|
+
|
|
14
19
|
jobs:
|
|
15
20
|
codeql:
|
|
16
21
|
name: Scanning
|
|
17
22
|
runs-on: ubuntu-latest
|
|
18
23
|
steps:
|
|
19
24
|
- name: ⤵️ Check out code from GitHub
|
|
20
|
-
uses: actions/checkout@v6.0.
|
|
25
|
+
uses: actions/checkout@v6.0.2
|
|
21
26
|
- name: 🏗 Initialize CodeQL
|
|
22
|
-
uses: github/codeql-action/init@v4.
|
|
27
|
+
uses: github/codeql-action/init@v4.32.2
|
|
23
28
|
- name: 🚀 Perform CodeQL Analysis
|
|
24
|
-
uses: github/codeql-action/analyze@v4.
|
|
29
|
+
uses: github/codeql-action/analyze@v4.32.2
|
|
@@ -10,13 +10,17 @@ on:
|
|
|
10
10
|
- .github/labels.yml
|
|
11
11
|
workflow_dispatch:
|
|
12
12
|
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
issues: write
|
|
16
|
+
|
|
13
17
|
jobs:
|
|
14
18
|
labels:
|
|
15
19
|
name: ♻️ Sync labels
|
|
16
20
|
runs-on: ubuntu-latest
|
|
17
21
|
steps:
|
|
18
22
|
- name: ⤵️ Check out code from GitHub
|
|
19
|
-
uses: actions/checkout@v6.0.
|
|
23
|
+
uses: actions/checkout@v6.0.2
|
|
20
24
|
- name: 🚀 Run Label Syncer
|
|
21
25
|
uses: micnncim/action-label-syncer@v1.3.0
|
|
22
26
|
env:
|
|
@@ -9,6 +9,9 @@ on:
|
|
|
9
9
|
branches: [main]
|
|
10
10
|
workflow_dispatch:
|
|
11
11
|
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
12
15
|
env:
|
|
13
16
|
DEFAULT_PYTHON: "3.13"
|
|
14
17
|
|
|
@@ -18,14 +21,14 @@ jobs:
|
|
|
18
21
|
runs-on: ubuntu-latest
|
|
19
22
|
steps:
|
|
20
23
|
- name: ⤵️ Check out code from GitHub
|
|
21
|
-
uses: actions/checkout@v6.0.
|
|
24
|
+
uses: actions/checkout@v6.0.2
|
|
22
25
|
- name: 🏗 Set up uv
|
|
23
26
|
uses: astral-sh/setup-uv@v7
|
|
24
27
|
with:
|
|
25
28
|
enable-cache: true
|
|
26
29
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
27
30
|
id: python
|
|
28
|
-
uses: actions/setup-python@v6.
|
|
31
|
+
uses: actions/setup-python@v6.2.0
|
|
29
32
|
with:
|
|
30
33
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
31
34
|
- name: 🏗 Install Python dependencies
|
|
@@ -38,14 +41,14 @@ jobs:
|
|
|
38
41
|
runs-on: ubuntu-latest
|
|
39
42
|
steps:
|
|
40
43
|
- name: ⤵️ Check out code from GitHub
|
|
41
|
-
uses: actions/checkout@v6.0.
|
|
44
|
+
uses: actions/checkout@v6.0.2
|
|
42
45
|
- name: 🏗 Set up uv
|
|
43
46
|
uses: astral-sh/setup-uv@v7
|
|
44
47
|
with:
|
|
45
48
|
enable-cache: true
|
|
46
49
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
47
50
|
id: python
|
|
48
|
-
uses: actions/setup-python@v6.
|
|
51
|
+
uses: actions/setup-python@v6.2.0
|
|
49
52
|
with:
|
|
50
53
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
51
54
|
- name: 🏗 Install Python dependencies
|
|
@@ -60,14 +63,14 @@ jobs:
|
|
|
60
63
|
runs-on: ubuntu-latest
|
|
61
64
|
steps:
|
|
62
65
|
- name: ⤵️ Check out code from GitHub
|
|
63
|
-
uses: actions/checkout@v6.0.
|
|
66
|
+
uses: actions/checkout@v6.0.2
|
|
64
67
|
- name: 🏗 Set up uv
|
|
65
68
|
uses: astral-sh/setup-uv@v7
|
|
66
69
|
with:
|
|
67
70
|
enable-cache: true
|
|
68
71
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
69
72
|
id: python
|
|
70
|
-
uses: actions/setup-python@v6.
|
|
73
|
+
uses: actions/setup-python@v6.2.0
|
|
71
74
|
with:
|
|
72
75
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
73
76
|
- name: 🏗 Install Python dependencies
|
|
@@ -104,14 +107,14 @@ jobs:
|
|
|
104
107
|
runs-on: ubuntu-latest
|
|
105
108
|
steps:
|
|
106
109
|
- name: ⤵️ Check out code from GitHub
|
|
107
|
-
uses: actions/checkout@v6.0.
|
|
110
|
+
uses: actions/checkout@v6.0.2
|
|
108
111
|
- name: 🏗 Set up uv
|
|
109
112
|
uses: astral-sh/setup-uv@v7
|
|
110
113
|
with:
|
|
111
114
|
enable-cache: true
|
|
112
115
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
113
116
|
id: python
|
|
114
|
-
uses: actions/setup-python@v6.
|
|
117
|
+
uses: actions/setup-python@v6.2.0
|
|
115
118
|
with:
|
|
116
119
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
117
120
|
- name: 🏗 Install Python dependencies
|
|
@@ -124,14 +127,14 @@ jobs:
|
|
|
124
127
|
runs-on: ubuntu-latest
|
|
125
128
|
steps:
|
|
126
129
|
- name: ⤵️ Check out code from GitHub
|
|
127
|
-
uses: actions/checkout@v6.0.
|
|
130
|
+
uses: actions/checkout@v6.0.2
|
|
128
131
|
- name: 🏗 Set up uv
|
|
129
132
|
uses: astral-sh/setup-uv@v7
|
|
130
133
|
with:
|
|
131
134
|
enable-cache: true
|
|
132
135
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
133
136
|
id: python
|
|
134
|
-
uses: actions/setup-python@v6.
|
|
137
|
+
uses: actions/setup-python@v6.2.0
|
|
135
138
|
with:
|
|
136
139
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
137
140
|
- name: 🏗 Install Python dependencies
|
|
@@ -144,20 +147,20 @@ jobs:
|
|
|
144
147
|
runs-on: ubuntu-latest
|
|
145
148
|
steps:
|
|
146
149
|
- name: ⤵️ Check out code from GitHub
|
|
147
|
-
uses: actions/checkout@v6.0.
|
|
150
|
+
uses: actions/checkout@v6.0.2
|
|
148
151
|
- name: 🏗 Set up uv
|
|
149
152
|
uses: astral-sh/setup-uv@v7
|
|
150
153
|
with:
|
|
151
154
|
enable-cache: true
|
|
152
155
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
153
156
|
id: python
|
|
154
|
-
uses: actions/setup-python@v6.
|
|
157
|
+
uses: actions/setup-python@v6.2.0
|
|
155
158
|
with:
|
|
156
159
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
157
160
|
- name: 🏗 Install Python dependencies
|
|
158
161
|
run: uv sync --dev
|
|
159
162
|
- name: 🏗 Set up Node.js
|
|
160
|
-
uses: actions/setup-node@v6.
|
|
163
|
+
uses: actions/setup-node@v6.2.0
|
|
161
164
|
with:
|
|
162
165
|
node-version-file: ".nvmrc"
|
|
163
166
|
cache: "npm"
|
|
@@ -23,13 +23,18 @@ on:
|
|
|
23
23
|
- alpha
|
|
24
24
|
- rc
|
|
25
25
|
|
|
26
|
+
permissions:
|
|
27
|
+
contents: write
|
|
28
|
+
issues: read
|
|
29
|
+
pull-requests: read
|
|
30
|
+
|
|
26
31
|
jobs:
|
|
27
32
|
update_release_draft:
|
|
28
33
|
name: ✏️ Draft release
|
|
29
34
|
runs-on: ubuntu-latest
|
|
30
35
|
steps:
|
|
31
36
|
- name: 🚀 Run Release Drafter
|
|
32
|
-
uses: release-drafter/release-drafter@v6.
|
|
37
|
+
uses: release-drafter/release-drafter@v6.2.0
|
|
33
38
|
with:
|
|
34
39
|
prerelease: ${{ github.event.inputs.prerelease == 'true' }}
|
|
35
40
|
prerelease-identifier: ${{ github.event.inputs.prerelease_identifier }}
|
|
@@ -22,14 +22,14 @@ jobs:
|
|
|
22
22
|
id-token: write
|
|
23
23
|
steps:
|
|
24
24
|
- name: ⤵️ Check out code from GitHub
|
|
25
|
-
uses: actions/checkout@v6.0.
|
|
25
|
+
uses: actions/checkout@v6.0.2
|
|
26
26
|
- name: 🏗 Set up uv
|
|
27
27
|
uses: astral-sh/setup-uv@v7
|
|
28
28
|
with:
|
|
29
29
|
enable-cache: true
|
|
30
30
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
31
31
|
id: python
|
|
32
|
-
uses: actions/setup-python@v6.
|
|
32
|
+
uses: actions/setup-python@v6.2.0
|
|
33
33
|
with:
|
|
34
34
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
35
35
|
- name: 🏗 Install dependencies
|
|
@@ -9,6 +9,11 @@ on:
|
|
|
9
9
|
branches: [main]
|
|
10
10
|
workflow_dispatch:
|
|
11
11
|
|
|
12
|
+
permissions:
|
|
13
|
+
actions: write
|
|
14
|
+
contents: read
|
|
15
|
+
pull-requests: read
|
|
16
|
+
|
|
12
17
|
env:
|
|
13
18
|
DEFAULT_PYTHON: "3.13"
|
|
14
19
|
|
|
@@ -21,14 +26,14 @@ jobs:
|
|
|
21
26
|
python: ["3.12", "3.13", "3.14"]
|
|
22
27
|
steps:
|
|
23
28
|
- name: ⤵️ Check out code from GitHub
|
|
24
|
-
uses: actions/checkout@v6.0.
|
|
29
|
+
uses: actions/checkout@v6.0.2
|
|
25
30
|
- name: 🏗 Set up uv
|
|
26
31
|
uses: astral-sh/setup-uv@v7
|
|
27
32
|
with:
|
|
28
33
|
enable-cache: true
|
|
29
34
|
- name: 🏗 Set up Python ${{ matrix.python }}
|
|
30
35
|
id: python
|
|
31
|
-
uses: actions/setup-python@v6.
|
|
36
|
+
uses: actions/setup-python@v6.2.0
|
|
32
37
|
with:
|
|
33
38
|
python-version: ${{ matrix.python }}
|
|
34
39
|
- name: 🏗 Install dependencies
|
|
@@ -47,7 +52,7 @@ jobs:
|
|
|
47
52
|
needs: pytest
|
|
48
53
|
steps:
|
|
49
54
|
- name: ⤵️ Check out code from GitHub
|
|
50
|
-
uses: actions/checkout@v6.0.
|
|
55
|
+
uses: actions/checkout@v6.0.2
|
|
51
56
|
with:
|
|
52
57
|
fetch-depth: 0
|
|
53
58
|
- name: ⬇️ Download coverage data
|
|
@@ -58,7 +63,7 @@ jobs:
|
|
|
58
63
|
enable-cache: true
|
|
59
64
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
60
65
|
id: python
|
|
61
|
-
uses: actions/setup-python@v6.
|
|
66
|
+
uses: actions/setup-python@v6.2.0
|
|
62
67
|
with:
|
|
63
68
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
64
69
|
- name: 🏗 Install dependencies
|
|
@@ -20,14 +20,14 @@ jobs:
|
|
|
20
20
|
contents: read
|
|
21
21
|
steps:
|
|
22
22
|
- name: ⤵️ Check out code from GitHub
|
|
23
|
-
uses: actions/checkout@v6.0.
|
|
23
|
+
uses: actions/checkout@v6.0.2
|
|
24
24
|
- name: 🏗 Set up uv
|
|
25
25
|
uses: astral-sh/setup-uv@v7
|
|
26
26
|
with:
|
|
27
27
|
enable-cache: true
|
|
28
28
|
- name: 🏗 Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
29
29
|
id: python
|
|
30
|
-
uses: actions/setup-python@v6.
|
|
30
|
+
uses: actions/setup-python@v6.2.0
|
|
31
31
|
with:
|
|
32
32
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
33
33
|
- name: 🏗 Install dependencies
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24.13.1
|
|
@@ -177,8 +177,8 @@ async def print_device_info(device: Device, info: Info) -> None:
|
|
|
177
177
|
)
|
|
178
178
|
|
|
179
179
|
attributes = {
|
|
180
|
-
"Device Name": device.name
|
|
181
|
-
"Version": device.version
|
|
180
|
+
"Device Name": device.name or "N/A",
|
|
181
|
+
"Version": device.version or "N/A",
|
|
182
182
|
"Device Identification": device_identification,
|
|
183
183
|
}
|
|
184
184
|
print_attributes("Device Information", attributes)
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
"url-parse": "1.5.10"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"prettier": "3.
|
|
15
|
+
"prettier": "3.8.1"
|
|
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.8.1",
|
|
20
|
+
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
|
|
21
|
+
"integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
|
|
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 = "4.
|
|
3
|
+
version = "4.2.0"
|
|
4
4
|
description = "Asynchronous Python client for BSBLAN API"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Willem-Jan van Rootselaar", email = "liudgervr@gmail.com"}
|
|
@@ -177,19 +177,19 @@ build-backend = "hatchling.build"
|
|
|
177
177
|
[dependency-groups]
|
|
178
178
|
dev = [
|
|
179
179
|
"aresponses==3.0.0",
|
|
180
|
-
"bandit==1.9.
|
|
181
|
-
"black==
|
|
180
|
+
"bandit==1.9.3",
|
|
181
|
+
"black==26.1.0",
|
|
182
182
|
"blacken-docs==1.20.0",
|
|
183
183
|
"codespell==2.4.1",
|
|
184
184
|
"covdefaults==2.3.0",
|
|
185
|
-
"coverage==7.13.
|
|
185
|
+
"coverage==7.13.4",
|
|
186
186
|
"darglint==1.8.1",
|
|
187
187
|
"flake8==7.3.0",
|
|
188
188
|
"flake8-simplify==0.30.0",
|
|
189
189
|
# hatch is required to support type hinting and proper packaging of the py.typed file.
|
|
190
190
|
"hatch>=1.14.1",
|
|
191
191
|
"isort==7.0.0",
|
|
192
|
-
"ty==0.0.
|
|
192
|
+
"ty==0.0.16",
|
|
193
193
|
"pre-commit==4.5.1",
|
|
194
194
|
"pre-commit-hooks==6.0.0",
|
|
195
195
|
"pylint==4.0.4",
|
|
@@ -198,9 +198,9 @@ dev = [
|
|
|
198
198
|
"pytest-cov==7.0.0",
|
|
199
199
|
"pytest-xdist>=3.8.0",
|
|
200
200
|
"pyupgrade==3.21.2",
|
|
201
|
-
"ruff==0.
|
|
201
|
+
"ruff==0.15.0",
|
|
202
202
|
"safety==3.7.0",
|
|
203
203
|
"vulture==2.14",
|
|
204
|
-
"yamllint==1.
|
|
204
|
+
"yamllint==1.38.0",
|
|
205
205
|
"zeroconf>=0.148.0",
|
|
206
206
|
]
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from .bsblan import BSBLAN, BSBLANConfig
|
|
4
4
|
from .constants import (
|
|
5
|
+
UNIT_DEVICE_CLASS_MAP,
|
|
6
|
+
UNIT_STATE_CLASS_MAP,
|
|
5
7
|
HeatingCircuitStatus,
|
|
6
8
|
HVACActionCategory,
|
|
7
9
|
get_hvac_action_category,
|
|
@@ -27,6 +29,8 @@ from .models import (
|
|
|
27
29
|
|
|
28
30
|
__all__ = [
|
|
29
31
|
"BSBLAN",
|
|
32
|
+
"UNIT_DEVICE_CLASS_MAP",
|
|
33
|
+
"UNIT_STATE_CLASS_MAP",
|
|
30
34
|
"BSBLANAuthError",
|
|
31
35
|
"BSBLANConfig",
|
|
32
36
|
"BSBLANConnectionError",
|
|
@@ -415,6 +415,77 @@ EMPTY_INCLUDE_LIST_ERROR_MSG: Final[str] = (
|
|
|
415
415
|
# Handle both ASCII and Unicode degree symbols
|
|
416
416
|
TEMPERATURE_UNITS = {"°C", "°F", "°C", "°F", "°C", "°F"}
|
|
417
417
|
|
|
418
|
+
# HA-compatible device class mapping from BSB-LAN units
|
|
419
|
+
# Maps unit strings (incl. HTML-encoded variants)
|
|
420
|
+
# to HA SensorDeviceClass values
|
|
421
|
+
UNIT_DEVICE_CLASS_MAP: Final[dict[str, str]] = {
|
|
422
|
+
# Temperature
|
|
423
|
+
"°C": "temperature",
|
|
424
|
+
"°F": "temperature",
|
|
425
|
+
"°C": "temperature",
|
|
426
|
+
"°F": "temperature",
|
|
427
|
+
"°C": "temperature",
|
|
428
|
+
"°F": "temperature",
|
|
429
|
+
# Energy
|
|
430
|
+
"kWh": "energy",
|
|
431
|
+
"MWh": "energy",
|
|
432
|
+
"Wh": "energy",
|
|
433
|
+
# Power
|
|
434
|
+
"kW": "power",
|
|
435
|
+
"W": "power",
|
|
436
|
+
# Pressure
|
|
437
|
+
"bar": "pressure",
|
|
438
|
+
"Pa": "pressure",
|
|
439
|
+
"hPa": "pressure",
|
|
440
|
+
# Voltage
|
|
441
|
+
"V": "voltage",
|
|
442
|
+
# Current
|
|
443
|
+
"A": "current",
|
|
444
|
+
"mA": "current",
|
|
445
|
+
# Frequency
|
|
446
|
+
"Hz": "frequency",
|
|
447
|
+
# Volume flow rate
|
|
448
|
+
"l/min": "volume_flow_rate",
|
|
449
|
+
"l/h": "volume_flow_rate",
|
|
450
|
+
# Duration
|
|
451
|
+
"h": "duration",
|
|
452
|
+
"min": "duration",
|
|
453
|
+
"s": "duration",
|
|
454
|
+
# Percentage
|
|
455
|
+
"%": "power_factor",
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
# HA-compatible state class mapping from BSB-LAN units
|
|
459
|
+
# Maps unit strings to HA SensorStateClass values
|
|
460
|
+
UNIT_STATE_CLASS_MAP: Final[dict[str, str]] = {
|
|
461
|
+
# Energy counters are always total_increasing
|
|
462
|
+
"kWh": "total_increasing",
|
|
463
|
+
"MWh": "total_increasing",
|
|
464
|
+
"Wh": "total_increasing",
|
|
465
|
+
# All other numeric measurements
|
|
466
|
+
"°C": "measurement",
|
|
467
|
+
"°F": "measurement",
|
|
468
|
+
"°C": "measurement",
|
|
469
|
+
"°F": "measurement",
|
|
470
|
+
"°C": "measurement",
|
|
471
|
+
"°F": "measurement",
|
|
472
|
+
"kW": "measurement",
|
|
473
|
+
"W": "measurement",
|
|
474
|
+
"bar": "measurement",
|
|
475
|
+
"Pa": "measurement",
|
|
476
|
+
"hPa": "measurement",
|
|
477
|
+
"V": "measurement",
|
|
478
|
+
"A": "measurement",
|
|
479
|
+
"mA": "measurement",
|
|
480
|
+
"Hz": "measurement",
|
|
481
|
+
"l/min": "measurement",
|
|
482
|
+
"l/h": "measurement",
|
|
483
|
+
"%": "measurement",
|
|
484
|
+
"h": "measurement",
|
|
485
|
+
"min": "measurement",
|
|
486
|
+
"s": "measurement",
|
|
487
|
+
}
|
|
488
|
+
|
|
418
489
|
# Hot Water Parameter Groups
|
|
419
490
|
# Essential parameters for frequent monitoring
|
|
420
491
|
HOT_WATER_ESSENTIAL_PARAMS: Final[set[str]] = {
|
|
@@ -11,7 +11,11 @@ from typing import Any, Final
|
|
|
11
11
|
|
|
12
12
|
from mashumaro.mixins.json import DataClassJSONMixin
|
|
13
13
|
|
|
14
|
-
from bsblan.constants import
|
|
14
|
+
from bsblan.constants import (
|
|
15
|
+
TEMPERATURE_UNITS,
|
|
16
|
+
UNIT_DEVICE_CLASS_MAP,
|
|
17
|
+
UNIT_STATE_CLASS_MAP,
|
|
18
|
+
)
|
|
15
19
|
|
|
16
20
|
# Maximum number of time slots per day supported by BSB-LAN
|
|
17
21
|
MAX_TIME_SLOTS_PER_DAY: Final[int] = 3
|
|
@@ -225,6 +229,8 @@ class EntityInfo(DataClassJSONMixin):
|
|
|
225
229
|
readonly: Whether the value is read-only.
|
|
226
230
|
readwrite: Whether the value is read-write.
|
|
227
231
|
precision: Optional precision for numeric values.
|
|
232
|
+
data_type_name: BSB-LAN data type name (e.g., "TEMP", "ENUM").
|
|
233
|
+
data_type_family: BSB-LAN data type family (e.g., "VALS", "ENUM").
|
|
228
234
|
|
|
229
235
|
"""
|
|
230
236
|
|
|
@@ -237,6 +243,8 @@ class EntityInfo(DataClassJSONMixin):
|
|
|
237
243
|
readonly: int = field(default=0)
|
|
238
244
|
readwrite: int = field(default=0)
|
|
239
245
|
precision: float | None = field(default=None)
|
|
246
|
+
data_type_name: str = field(default="", metadata={"alias": "dataType_name"})
|
|
247
|
+
data_type_family: str = field(default="", metadata={"alias": "dataType_family"})
|
|
240
248
|
|
|
241
249
|
def __post_init__(self) -> None:
|
|
242
250
|
"""Convert values based on data_type after initialization."""
|
|
@@ -312,6 +320,45 @@ class EntityInfo(DataClassJSONMixin):
|
|
|
312
320
|
"""
|
|
313
321
|
return self.desc if self.data_type == DataType.ENUM else None
|
|
314
322
|
|
|
323
|
+
@property
|
|
324
|
+
def suggested_device_class(self) -> str | None:
|
|
325
|
+
"""Suggest HA SensorDeviceClass based on unit and data type.
|
|
326
|
+
|
|
327
|
+
Only PLAIN_NUMBER data types are considered sensor-like values.
|
|
328
|
+
Returns None for ENUM, TIME, WEEKDAY, STRING, and other
|
|
329
|
+
non-numeric types even if they carry a unit.
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
str | None: The suggested HA device class (e.g., "temperature",
|
|
333
|
+
"energy", "power"), or None if no mapping exists or the
|
|
334
|
+
data type is not numeric.
|
|
335
|
+
|
|
336
|
+
"""
|
|
337
|
+
if self.data_type != DataType.PLAIN_NUMBER:
|
|
338
|
+
return None
|
|
339
|
+
return UNIT_DEVICE_CLASS_MAP.get(self.unit)
|
|
340
|
+
|
|
341
|
+
@property
|
|
342
|
+
def suggested_state_class(self) -> str | None:
|
|
343
|
+
"""Suggest HA SensorStateClass based on unit and data type.
|
|
344
|
+
|
|
345
|
+
Only PLAIN_NUMBER data types are considered sensor-like values.
|
|
346
|
+
Returns None for ENUM, TIME, WEEKDAY, STRING, and other
|
|
347
|
+
non-numeric types even if they carry a unit.
|
|
348
|
+
|
|
349
|
+
Energy counters (kWh, MWh, Wh) are mapped to "total_increasing",
|
|
350
|
+
while other numeric measurements use "measurement".
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
str | None: The suggested HA state class (e.g., "measurement",
|
|
354
|
+
"total_increasing"), or None if the data type is not
|
|
355
|
+
numeric or no mapping exists.
|
|
356
|
+
|
|
357
|
+
"""
|
|
358
|
+
if self.data_type != DataType.PLAIN_NUMBER:
|
|
359
|
+
return None
|
|
360
|
+
return UNIT_STATE_CLASS_MAP.get(self.unit)
|
|
361
|
+
|
|
315
362
|
|
|
316
363
|
@dataclass
|
|
317
364
|
class SetHotWaterParam:
|