python-qube-heatpump 1.3.1__tar.gz → 1.4.1__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_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/PKG-INFO +1 -1
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/pyproject.toml +1 -1
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/client.py +55 -14
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/.github/workflows/ci.yml +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/.github/workflows/python-publish.yml +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/.gitignore +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/AGENTS.md +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/CLAUDE.md +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/LICENSE +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/README.md +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/pytest.ini +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/__init__.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/const.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/entities/__init__.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/entities/base.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/entities/binary_sensors.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/entities/sensors.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/entities/switches.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/models.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/py.typed +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/tests/conftest.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/tests/test_client.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/tests/test_const.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/tests/test_entities.py +0 -0
- {python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/tests/test_models.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-qube-heatpump
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1
|
|
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
|
{python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/client.py
RENAMED
|
@@ -33,17 +33,21 @@ class QubeClient:
|
|
|
33
33
|
self._connected = await self._client.connect()
|
|
34
34
|
return self._connected
|
|
35
35
|
|
|
36
|
+
@property
|
|
37
|
+
def is_connected(self) -> bool:
|
|
38
|
+
"""Return True if connected."""
|
|
39
|
+
return self._connected
|
|
40
|
+
|
|
36
41
|
async def close(self) -> None:
|
|
37
42
|
"""Close connection."""
|
|
38
43
|
self._client.close()
|
|
39
44
|
self._connected = False
|
|
40
45
|
|
|
41
46
|
async def get_all_data(self) -> QubeState:
|
|
42
|
-
"""Fetch all definition data and return a state object.
|
|
43
|
-
# Note: In a real implementation you might want to optimize this
|
|
44
|
-
# by reading contiguous blocks instead of one-by-one.
|
|
45
|
-
# For now, we wrap the individual reads for abstraction.
|
|
47
|
+
"""Fetch all definition data and return a state object.
|
|
46
48
|
|
|
49
|
+
This fetches core sensors for the official HA integration.
|
|
50
|
+
"""
|
|
47
51
|
state = QubeState()
|
|
48
52
|
|
|
49
53
|
# Helper to read and assign
|
|
@@ -80,6 +84,43 @@ class QubeClient:
|
|
|
80
84
|
|
|
81
85
|
return state
|
|
82
86
|
|
|
87
|
+
async def get_all_entities(self) -> dict[str, Any]:
|
|
88
|
+
"""Fetch all entity values from library definitions.
|
|
89
|
+
|
|
90
|
+
This reads all sensors, binary sensors, and switches defined in the
|
|
91
|
+
library's entity definitions. Used by the HACS integration.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Dictionary mapping entity keys to their values.
|
|
95
|
+
"""
|
|
96
|
+
results: dict[str, Any] = {}
|
|
97
|
+
|
|
98
|
+
# Read all sensors
|
|
99
|
+
for key, entity in SENSORS.items():
|
|
100
|
+
try:
|
|
101
|
+
results[key] = await self.read_entity(entity)
|
|
102
|
+
except Exception as exc:
|
|
103
|
+
_LOGGER.debug("Error reading sensor %s: %s", key, exc)
|
|
104
|
+
results[key] = None
|
|
105
|
+
|
|
106
|
+
# Read all binary sensors
|
|
107
|
+
for key, entity in BINARY_SENSORS.items():
|
|
108
|
+
try:
|
|
109
|
+
results[key] = await self.read_entity(entity)
|
|
110
|
+
except Exception as exc:
|
|
111
|
+
_LOGGER.debug("Error reading binary sensor %s: %s", key, exc)
|
|
112
|
+
results[key] = None
|
|
113
|
+
|
|
114
|
+
# Read all switches
|
|
115
|
+
for key, entity in SWITCHES.items():
|
|
116
|
+
try:
|
|
117
|
+
results[key] = await self.read_entity(entity)
|
|
118
|
+
except Exception as exc:
|
|
119
|
+
_LOGGER.debug("Error reading switch %s: %s", key, exc)
|
|
120
|
+
results[key] = None
|
|
121
|
+
|
|
122
|
+
return results
|
|
123
|
+
|
|
83
124
|
async def read_value(self, definition: tuple) -> float | None:
|
|
84
125
|
"""Read a single value based on the constant definition."""
|
|
85
126
|
address, reg_type, data_type, scale, offset = definition
|
|
@@ -94,11 +135,11 @@ class QubeClient:
|
|
|
94
135
|
try:
|
|
95
136
|
if reg_type == const.ModbusType.INPUT:
|
|
96
137
|
result = await self._client.read_input_registers(
|
|
97
|
-
address, count,
|
|
138
|
+
address, count=count, slave=self.unit
|
|
98
139
|
)
|
|
99
140
|
else:
|
|
100
141
|
result = await self._client.read_holding_registers(
|
|
101
|
-
address, count,
|
|
142
|
+
address, count=count, slave=self.unit
|
|
102
143
|
)
|
|
103
144
|
|
|
104
145
|
if result.isError():
|
|
@@ -180,7 +221,7 @@ class QubeClient:
|
|
|
180
221
|
# Read based on input type
|
|
181
222
|
if entity.input_type == InputType.COIL:
|
|
182
223
|
result = await self._client.read_coils(
|
|
183
|
-
entity.address, count=1,
|
|
224
|
+
entity.address, count=1, slave=self.unit
|
|
184
225
|
)
|
|
185
226
|
if result.isError():
|
|
186
227
|
_LOGGER.warning("Error reading coil %s", entity.address)
|
|
@@ -189,7 +230,7 @@ class QubeClient:
|
|
|
189
230
|
|
|
190
231
|
if entity.input_type == InputType.DISCRETE_INPUT:
|
|
191
232
|
result = await self._client.read_discrete_inputs(
|
|
192
|
-
entity.address, count=1,
|
|
233
|
+
entity.address, count=1, slave=self.unit
|
|
193
234
|
)
|
|
194
235
|
if result.isError():
|
|
195
236
|
_LOGGER.warning("Error reading discrete input %s", entity.address)
|
|
@@ -198,11 +239,11 @@ class QubeClient:
|
|
|
198
239
|
|
|
199
240
|
if entity.input_type == InputType.INPUT_REGISTER:
|
|
200
241
|
result = await self._client.read_input_registers(
|
|
201
|
-
entity.address, count,
|
|
242
|
+
entity.address, count=count, slave=self.unit
|
|
202
243
|
)
|
|
203
244
|
else: # HOLDING_REGISTER
|
|
204
245
|
result = await self._client.read_holding_registers(
|
|
205
|
-
entity.address, count,
|
|
246
|
+
entity.address, count=count, slave=self.unit
|
|
206
247
|
)
|
|
207
248
|
|
|
208
249
|
if result.isError():
|
|
@@ -340,7 +381,7 @@ class QubeClient:
|
|
|
340
381
|
|
|
341
382
|
try:
|
|
342
383
|
result = await self._client.write_coil(
|
|
343
|
-
entity.address, value,
|
|
384
|
+
entity.address, value, slave=self.unit
|
|
344
385
|
)
|
|
345
386
|
if result.isError():
|
|
346
387
|
_LOGGER.warning("Error writing switch %s", key)
|
|
@@ -388,17 +429,17 @@ class QubeClient:
|
|
|
388
429
|
int_val = struct.unpack(">I", packed)[0]
|
|
389
430
|
regs = [int_val & 0xFFFF, (int_val >> 16) & 0xFFFF]
|
|
390
431
|
result = await self._client.write_registers(
|
|
391
|
-
entity.address, regs,
|
|
432
|
+
entity.address, regs, slave=self.unit
|
|
392
433
|
)
|
|
393
434
|
elif entity.data_type == DataType.INT16:
|
|
394
435
|
if write_value < 0:
|
|
395
436
|
write_value = int(write_value) + 65536
|
|
396
437
|
result = await self._client.write_register(
|
|
397
|
-
entity.address, int(write_value),
|
|
438
|
+
entity.address, int(write_value), slave=self.unit
|
|
398
439
|
)
|
|
399
440
|
elif entity.data_type == DataType.UINT16:
|
|
400
441
|
result = await self._client.write_register(
|
|
401
|
-
entity.address, int(write_value),
|
|
442
|
+
entity.address, int(write_value), slave=self.unit
|
|
402
443
|
)
|
|
403
444
|
else:
|
|
404
445
|
_LOGGER.warning("Unsupported data type for writing: %s", entity.data_type)
|
{python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/.github/ISSUE_TEMPLATE/bug_report.yml
RENAMED
|
File without changes
|
|
File without changes
|
{python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/.github/ISSUE_TEMPLATE/feature_request.yml
RENAMED
|
File without changes
|
|
File without changes
|
{python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/.github/workflows/python-publish.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/entities/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_qube_heatpump-1.3.1 → python_qube_heatpump-1.4.1}/src/python_qube_heatpump/models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|