python-qube-heatpump 1.2.2__tar.gz → 1.3.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.
Files changed (31) hide show
  1. python_qube_heatpump-1.3.0/AGENTS.md +129 -0
  2. python_qube_heatpump-1.3.0/CLAUDE.md +245 -0
  3. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/PKG-INFO +1 -1
  4. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/pyproject.toml +1 -1
  5. python_qube_heatpump-1.3.0/src/python_qube_heatpump/__init__.py +39 -0
  6. python_qube_heatpump-1.3.0/src/python_qube_heatpump/client.py +414 -0
  7. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/src/python_qube_heatpump/const.py +36 -0
  8. python_qube_heatpump-1.3.0/src/python_qube_heatpump/entities/__init__.py +16 -0
  9. python_qube_heatpump-1.3.0/src/python_qube_heatpump/entities/base.py +77 -0
  10. python_qube_heatpump-1.3.0/src/python_qube_heatpump/entities/binary_sensors.py +269 -0
  11. python_qube_heatpump-1.3.0/src/python_qube_heatpump/entities/sensors.py +468 -0
  12. python_qube_heatpump-1.3.0/src/python_qube_heatpump/entities/switches.py +65 -0
  13. python_qube_heatpump-1.3.0/src/python_qube_heatpump/models.py +55 -0
  14. python_qube_heatpump-1.3.0/tests/test_client.py +223 -0
  15. python_qube_heatpump-1.3.0/tests/test_const.py +57 -0
  16. python_qube_heatpump-1.3.0/tests/test_entities.py +178 -0
  17. python_qube_heatpump-1.3.0/tests/test_models.py +64 -0
  18. python_qube_heatpump-1.2.2/src/python_qube_heatpump/__init__.py +0 -3
  19. python_qube_heatpump-1.2.2/src/python_qube_heatpump/client.py +0 -136
  20. python_qube_heatpump-1.2.2/src/python_qube_heatpump/models.py +0 -37
  21. python_qube_heatpump-1.2.2/tests/test_client.py +0 -73
  22. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  23. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  24. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  25. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/.github/workflows/ci.yml +0 -0
  26. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/.github/workflows/python-publish.yml +0 -0
  27. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/.gitignore +0 -0
  28. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/LICENSE +0 -0
  29. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/README.md +0 -0
  30. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/pytest.ini +0 -0
  31. {python_qube_heatpump-1.2.2 → python_qube_heatpump-1.3.0}/tests/conftest.py +0 -0
@@ -0,0 +1,129 @@
1
+ # Agents Instructions for python-qube-heatpump
2
+
3
+ ## Overview
4
+
5
+ Async Python library for Qube Heat Pump communication via Modbus TCP. Used by the Home Assistant `qube_heatpump` integration.
6
+
7
+ ## Quick Reference
8
+
9
+ | Item | Location |
10
+ |------|----------|
11
+ | Main client | `src/python_qube_heatpump/client.py` |
12
+ | Data model | `src/python_qube_heatpump/models.py` |
13
+ | Register definitions | `src/python_qube_heatpump/const.py` |
14
+ | Tests | `tests/test_client.py` |
15
+ | Version | `pyproject.toml` → `project.version` |
16
+
17
+ ## Current Version: 1.2.3
18
+
19
+ ### Recent Changes (1.2.3)
20
+ - `get_all_data()` now fetches all 21 sensor fields (previously only 4)
21
+ - Full compatibility with Home Assistant qube_heatpump integration
22
+
23
+ ## Testing
24
+
25
+ ```bash
26
+ # Setup
27
+ python3 -m venv .venv && source .venv/bin/activate && pip install -e ".[test]"
28
+
29
+ # Run tests
30
+ pytest tests/ -v
31
+ ```
32
+
33
+ ## Adding New Sensors
34
+
35
+ 1. **Add register definition** in `const.py`:
36
+ ```python
37
+ NEW_SENSOR = (address, ModbusType.INPUT, DataType.FLOAT32, scale, offset)
38
+ ```
39
+
40
+ 2. **Add field** to `QubeState` in `models.py`:
41
+ ```python
42
+ new_sensor: Optional[float] = None
43
+ ```
44
+
45
+ 3. **Fetch in `get_all_data()`** in `client.py`:
46
+ ```python
47
+ state.new_sensor = await _read(const.NEW_SENSOR)
48
+ ```
49
+
50
+ 4. **Update Home Assistant integration** to use the new field
51
+
52
+ ## Data Types
53
+
54
+ | DataType | Registers | Notes |
55
+ |----------|-----------|-------|
56
+ | FLOAT32 | 2 | Little-endian word order |
57
+ | INT16 | 1 | Signed |
58
+ | UINT16 | 1 | Unsigned |
59
+ | INT32 | 2 | Little-endian word order |
60
+ | UINT32 | 2 | Little-endian word order |
61
+
62
+ ## Related Repository
63
+
64
+ Home Assistant integration: `/Users/matthijskeij/Github/core/homeassistant/components/qube_heatpump/`
65
+
66
+ When making changes, test both repos together:
67
+ ```bash
68
+ # In HA core repo
69
+ pip install -e /Users/matthijskeij/Github/python-qube-heatpump
70
+ pytest tests/components/qube_heatpump -v
71
+ ```
72
+
73
+ ## Release Checklist
74
+
75
+ - [ ] Update version in `pyproject.toml`
76
+ - [ ] Run tests: `pytest tests/ -v`
77
+ - [ ] Run linting: `ruff check src/ && ruff format --check src/`
78
+ - [ ] Commit and push
79
+ - [ ] Tag release: `git tag -a v1.x.x -m "Release message" && git push origin main --tags`
80
+ - [ ] Verify PyPI publish (GitHub Action)
81
+ - [ ] Update HA integration manifest.json with new version
82
+ - [ ] Run HA integration tests
83
+
84
+ ---
85
+
86
+ ## Architecture Decisions (Quick Reference)
87
+
88
+ See `CLAUDE.md` for detailed rationale.
89
+
90
+ ### Entity Definitions
91
+ - **Library defines**: key, name, address, input_type, data_type, unit, scale, offset, platform, writable
92
+ - **Integration adds**: device_class, state_class, suggested_display_precision, translation_key, icon
93
+
94
+ ### File Structure (Target)
95
+ ```
96
+ src/python_qube_heatpump/
97
+ ├── entities/
98
+ │ ├── __init__.py # Combined registry
99
+ │ ├── base.py # EntityDef dataclass
100
+ │ ├── sensors.py # Sensor definitions
101
+ │ ├── binary_sensors.py # Binary sensor definitions
102
+ │ └── switches.py # Switch definitions
103
+ ```
104
+
105
+ ### QubeState Strategy
106
+ - Keep typed fields for core sensors (backward compatible with official HA)
107
+ - Add `_extended: dict` for additional HACS entities
108
+ - Use `state.get("key")` for extended entities
109
+ - Promote to typed field when moving to official HA
110
+
111
+ ### QubeClient API
112
+ ```python
113
+ # Type-specific reads
114
+ read_sensor(entity) -> float | int | None
115
+ read_binary_sensor(entity) -> bool | None
116
+ read_switch_state(entity) -> bool | None
117
+
118
+ # Writes
119
+ write_switch(entity, value: bool) -> None
120
+ write_setpoint(entity, value: float) -> None
121
+
122
+ # Bulk
123
+ get_all_data() -> QubeState # Backward compatible
124
+ read_entities(entities) -> dict[str, Any]
125
+ ```
126
+
127
+ ### Related Repos
128
+ - HACS: `~/Github/qube_heatpump`
129
+ - Official HA: `~/Github/core/homeassistant/components/qube_heatpump/`
@@ -0,0 +1,245 @@
1
+ # Claude Code Instructions for python-qube-heatpump
2
+
3
+ This is an async Python library for communicating with Qube Heat Pumps via Modbus TCP.
4
+
5
+ ## Project Structure
6
+
7
+ ```
8
+ python-qube-heatpump/
9
+ ├── src/python_qube_heatpump/
10
+ │ ├── __init__.py # Exports QubeClient
11
+ │ ├── client.py # Main QubeClient class with Modbus communication
12
+ │ ├── const.py # Modbus register definitions (addresses, types, scales)
13
+ │ └── models.py # QubeState dataclass with all sensor fields
14
+ ├── tests/
15
+ │ ├── conftest.py # Pytest fixtures for mocking Modbus client
16
+ │ └── test_client.py # Unit tests for QubeClient
17
+ ├── pyproject.toml # Package configuration and dependencies
18
+ └── pytest.ini # Pytest configuration
19
+ ```
20
+
21
+ ## Key Components
22
+
23
+ ### QubeClient (client.py)
24
+ - Async Modbus TCP client using `pymodbus`
25
+ - `connect()` - Establish connection to heat pump
26
+ - `close()` - Close connection
27
+ - `get_all_data()` - Fetch all sensor values, returns `QubeState`
28
+ - `read_value(definition)` - Read a single register based on const definition
29
+
30
+ ### QubeState (models.py)
31
+ Dataclass containing all sensor values:
32
+ - **Temperatures**: `temp_supply`, `temp_return`, `temp_source_in`, `temp_source_out`, `temp_room`, `temp_dhw`, `temp_outside`
33
+ - **Power/Energy**: `power_thermic`, `power_electric`, `energy_total_electric`, `energy_total_thermic`, `cop_calc`
34
+ - **Operation**: `status_code`, `compressor_speed`, `flow_rate`
35
+ - **Setpoints**: `setpoint_room_heat_day`, `setpoint_room_heat_night`, `setpoint_room_cool_day`, `setpoint_room_cool_night`, `setpoint_dhw`
36
+
37
+ ### Register Definitions (const.py)
38
+ Each register is defined as: `(address, ModbusType, DataType, scale, offset)`
39
+ - `ModbusType`: `INPUT` or `HOLDING`
40
+ - `DataType`: `FLOAT32`, `INT16`, `UINT16`, `INT32`, `UINT32`
41
+
42
+ ## Development Commands
43
+
44
+ ### Setup
45
+ ```bash
46
+ python3 -m venv .venv
47
+ source .venv/bin/activate
48
+ pip install -e ".[test]"
49
+ ```
50
+
51
+ ### Run Tests
52
+ ```bash
53
+ pytest tests/ -v
54
+ ```
55
+
56
+ ### Linting
57
+ ```bash
58
+ pip install ruff
59
+ ruff check src/
60
+ ruff format src/
61
+ ```
62
+
63
+ ## Integration with Home Assistant
64
+
65
+ This library is used by the `qube_heatpump` integration in Home Assistant core:
66
+ - **Repo**: https://github.com/home-assistant/core
67
+ - **Integration path**: `homeassistant/components/qube_heatpump/`
68
+ - **Manifest requirement**: `python-qube-heatpump==<version>`
69
+
70
+ ### Compatibility Requirements
71
+
72
+ When modifying `QubeState` or `get_all_data()`:
73
+ 1. All fields in `QubeState` must be populated by `get_all_data()`
74
+ 2. The Home Assistant integration's sensors depend on these field names
75
+ 3. Test both repos together before releasing
76
+
77
+ ### Testing with Home Assistant Integration
78
+
79
+ ```bash
80
+ # Install library in editable mode in HA core venv
81
+ cd /path/to/home-assistant/core
82
+ source venv/bin/activate
83
+ pip install -e /path/to/python-qube-heatpump
84
+
85
+ # Run integration tests
86
+ pytest tests/components/qube_heatpump --cov=homeassistant.components.qube_heatpump
87
+ ```
88
+
89
+ ## Versioning and Release
90
+
91
+ 1. Update version in `pyproject.toml`
92
+ 2. Commit changes
93
+ 3. Create and push tag: `git tag -a v1.x.x -m "Release 1.x.x" && git push origin main --tags`
94
+ 4. GitHub Action automatically publishes to PyPI on tag push
95
+ 5. Update Home Assistant integration's `manifest.json` to require new version
96
+
97
+ ## Code Style
98
+
99
+ - Use async/await for all I/O operations
100
+ - Type hints on all functions
101
+ - Docstrings for public methods
102
+ - Follow ruff formatting rules
103
+
104
+ ---
105
+
106
+ ## Architecture Design Decisions (HACS → Official HA Transition)
107
+
108
+ This section documents architectural decisions made to ensure smooth transition between:
109
+ - **HACS integration**: `~/Github/qube_heatpump` (feature-complete with ~400 entities)
110
+ - **Official HA integration**: `~/Github/core/homeassistant/components/qube_heatpump/` (currently sensors only)
111
+
112
+ ### 1. Entity Definitions Location
113
+
114
+ **Decision**: Hybrid approach - library defines protocol-level properties, integration adds HA-specific metadata.
115
+
116
+ **Library (`python-qube-heatpump`) defines**:
117
+ - `key`: Unique identifier (e.g., `"temp_supply"`)
118
+ - `name`: Human-readable name
119
+ - `address`: Modbus register/coil address
120
+ - `input_type`: COIL, DISCRETE_INPUT, INPUT_REGISTER, HOLDING_REGISTER
121
+ - `data_type`: FLOAT32, INT16, UINT16, etc. (None for boolean types)
122
+ - `unit`: Standard units (°C, kWh, W, %, L/min)
123
+ - `scale`, `offset`: Protocol-level value transformations
124
+ - `platform`: SENSOR, BINARY_SENSOR, SWITCH
125
+ - `writable`: Boolean for write capability
126
+
127
+ **Integration adds**:
128
+ - `device_class`, `state_class`: HA-specific semantics
129
+ - `suggested_display_precision`: Display formatting
130
+ - `entity_category`, `translation_key`, `icon`: HA presentation
131
+
132
+ **Rationale**: Keeps library reusable for non-HA applications while centralizing ~400 entity definitions.
133
+
134
+ ### 2. Entity Organization in Library
135
+
136
+ **Decision**: Platform-based modules
137
+
138
+ ```
139
+ src/python_qube_heatpump/
140
+ ├── entities/
141
+ │ ├── __init__.py # Exports all entities + combined registry
142
+ │ ├── base.py # EntityDef dataclass + enums
143
+ │ ├── sensors.py # ~300 sensor definitions
144
+ │ ├── binary_sensors.py # ~50 binary sensor definitions
145
+ │ └── switches.py # ~20 switch definitions
146
+ ```
147
+
148
+ **Rationale**: Mirrors HA platform organization, easier maintenance.
149
+
150
+ ### 3. EntityDef Dataclass Structure
151
+
152
+ ```python
153
+ @dataclass(frozen=True)
154
+ class EntityDef:
155
+ """Definition of a Qube heat pump entity."""
156
+
157
+ # Identity
158
+ key: str # Unique identifier
159
+ name: str # Human-readable name
160
+
161
+ # Modbus specifics
162
+ address: int # Register/coil address
163
+ input_type: InputType # COIL, DISCRETE_INPUT, INPUT_REGISTER, HOLDING_REGISTER
164
+ data_type: DataType | None = None # FLOAT32, INT16, etc. (None for coils)
165
+
166
+ # Platform hint
167
+ platform: Platform # SENSOR, BINARY_SENSOR, SWITCH
168
+
169
+ # Value transformation
170
+ scale: float | None = None
171
+ offset: float | None = None
172
+
173
+ # Unit (protocol-level)
174
+ unit: str | None = None # "°C", "kWh", "W", "%", "L/min"
175
+
176
+ # Write capability
177
+ writable: bool = False
178
+ ```
179
+
180
+ ### 4. QubeClient API Methods
181
+
182
+ **Decision**: Type-specific methods for clarity and type safety.
183
+
184
+ ```python
185
+ # Reading
186
+ async def read_sensor(self, entity: EntityDef) -> float | int | None
187
+ async def read_binary_sensor(self, entity: EntityDef) -> bool | None
188
+ async def read_switch_state(self, entity: EntityDef) -> bool | None
189
+
190
+ # Writing
191
+ async def write_switch(self, entity: EntityDef, value: bool) -> None
192
+ async def write_setpoint(self, entity: EntityDef, value: float) -> None
193
+
194
+ # Bulk operations
195
+ async def get_all_data(self) -> QubeState # Backward compatible
196
+ async def read_entities(self, entities: list[EntityDef]) -> dict[str, Any]
197
+ ```
198
+
199
+ ### 5. QubeState Model Strategy
200
+
201
+ **Decision**: Keep typed fields for core sensors, add `_extended` dict for additional entities.
202
+
203
+ ```python
204
+ @dataclass
205
+ class QubeState:
206
+ """State of the Qube Heat Pump."""
207
+
208
+ # Core sensors (official HA integration uses these directly)
209
+ temp_supply: float | None = None
210
+ temp_return: float | None = None
211
+ # ... all existing 18 fields ...
212
+
213
+ # Extended data for additional HACS entities
214
+ _extended: dict[str, Any] = field(default_factory=dict)
215
+
216
+ def get(self, key: str, default: Any = None) -> Any:
217
+ """Get value by key, checking typed fields first, then extended."""
218
+ if hasattr(self, key) and not key.startswith('_'):
219
+ val = getattr(self, key)
220
+ if val is not None:
221
+ return val
222
+ return self._extended.get(key, default)
223
+ ```
224
+
225
+ **Transition workflow (HACS → Official)**:
226
+ 1. HACS uses `state.get("new_sensor")` for extended entities
227
+ 2. When promoting to official: add typed field to `QubeState`
228
+ 3. Official integration uses `state.new_sensor` directly
229
+ 4. No breaking changes - both integrations work with same library version
230
+
231
+ ### 6. Related Repositories
232
+
233
+ | Repository | Path | Purpose |
234
+ |------------|------|---------|
235
+ | python-qube-heatpump | `~/Github/python-qube-heatpump` | This library |
236
+ | HACS integration | `~/Github/qube_heatpump` | Feature-complete custom component |
237
+ | Official HA integration | `~/Github/core/homeassistant/components/qube_heatpump/` | Official HA core integration |
238
+
239
+ ### 7. Testing Strategy
240
+
241
+ When making changes:
242
+ 1. Run library tests: `pytest tests/ -v`
243
+ 2. Install in HACS integration and test: `pip install -e ~/Github/python-qube-heatpump`
244
+ 3. Install in HA core and test: `pytest tests/components/qube_heatpump -v`
245
+ 4. Ensure no breaking changes to official integration's `QubeState` field access
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-qube-heatpump
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: Async Modbus client for Qube Heat Pumps
5
5
  Project-URL: Homepage, https://github.com/MattieGit/python-qube-heatpump
6
6
  Project-URL: Bug Tracker, https://github.com/MattieGit/python-qube-heatpump/issues
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "python-qube-heatpump"
7
- version = "1.2.2"
7
+ version = "1.3.0"
8
8
  authors = [
9
9
  { name="MattieGit", email="6250046+MattieGit@users.noreply.github.com" },
10
10
  ]
@@ -0,0 +1,39 @@
1
+ """Python library for Qube Heat Pump Modbus communication."""
2
+
3
+ from .client import QubeClient
4
+ from .const import (
5
+ DataType,
6
+ ModbusType,
7
+ StatusCode,
8
+ STATUS_CODE_MAP,
9
+ get_status_code,
10
+ )
11
+ from .entities import (
12
+ BINARY_SENSORS,
13
+ EntityDef,
14
+ InputType,
15
+ Platform,
16
+ SENSORS,
17
+ SWITCHES,
18
+ )
19
+ from .models import QubeState
20
+
21
+ __all__ = [
22
+ # Client
23
+ "QubeClient",
24
+ # State
25
+ "QubeState",
26
+ # Entity definitions
27
+ "BINARY_SENSORS",
28
+ "EntityDef",
29
+ "InputType",
30
+ "Platform",
31
+ "SENSORS",
32
+ "SWITCHES",
33
+ # Constants
34
+ "DataType",
35
+ "ModbusType",
36
+ "StatusCode",
37
+ "STATUS_CODE_MAP",
38
+ "get_status_code",
39
+ ]