python-qube-heatpump 1.4.1__tar.gz → 1.4.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_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/PKG-INFO +2 -2
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/pyproject.toml +2 -2
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/client.py +44 -22
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/workflows/ci.yml +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/workflows/python-publish.yml +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.gitignore +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/AGENTS.md +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/CLAUDE.md +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/LICENSE +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/README.md +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/pytest.ini +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/__init__.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/const.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/__init__.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/base.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/binary_sensors.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/sensors.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/switches.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/models.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/py.typed +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/tests/conftest.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/tests/test_client.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/tests/test_const.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/tests/test_entities.py +0 -0
- {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/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.4.
|
|
3
|
+
Version: 1.4.3
|
|
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
|
|
@@ -10,7 +10,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
|
-
Requires-Dist: pymodbus>=3.
|
|
13
|
+
Requires-Dist: pymodbus>=3.11.0
|
|
14
14
|
Provides-Extra: test
|
|
15
15
|
Requires-Dist: pytest; extra == 'test'
|
|
16
16
|
Requires-Dist: pytest-asyncio; extra == 'test'
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-qube-heatpump"
|
|
7
|
-
version = "1.4.
|
|
7
|
+
version = "1.4.3"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="MattieGit", email="6250046+MattieGit@users.noreply.github.com" },
|
|
10
10
|
]
|
|
@@ -17,7 +17,7 @@ classifiers = [
|
|
|
17
17
|
"Operating System :: OS Independent",
|
|
18
18
|
]
|
|
19
19
|
dependencies = [
|
|
20
|
-
"pymodbus>=3.
|
|
20
|
+
"pymodbus>=3.11.0",
|
|
21
21
|
]
|
|
22
22
|
|
|
23
23
|
[project.optional-dependencies]
|
{python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/client.py
RENAMED
|
@@ -135,11 +135,11 @@ class QubeClient:
|
|
|
135
135
|
try:
|
|
136
136
|
if reg_type == const.ModbusType.INPUT:
|
|
137
137
|
result = await self._client.read_input_registers(
|
|
138
|
-
address, count=count,
|
|
138
|
+
address, count=count, device_id=self.unit
|
|
139
139
|
)
|
|
140
140
|
else:
|
|
141
141
|
result = await self._client.read_holding_registers(
|
|
142
|
-
address, count=count,
|
|
142
|
+
address, count=count, device_id=self.unit
|
|
143
143
|
)
|
|
144
144
|
|
|
145
145
|
if result.isError():
|
|
@@ -212,38 +212,47 @@ class QubeClient:
|
|
|
212
212
|
The read value (float, int, or bool depending on entity type).
|
|
213
213
|
"""
|
|
214
214
|
# Determine register count based on data type
|
|
215
|
-
|
|
215
|
+
# Use string comparison to handle potential enum class differences
|
|
216
|
+
data_type_str = entity.data_type.value if entity.data_type else None
|
|
217
|
+
if data_type_str in ("float32", "uint32", "int32"):
|
|
216
218
|
count = 2
|
|
217
219
|
else:
|
|
218
220
|
count = 1
|
|
219
221
|
|
|
222
|
+
_LOGGER.debug(
|
|
223
|
+
"read_entity: key=%s addr=%s input_type=%s data_type=%s count=%s",
|
|
224
|
+
entity.key, entity.address, entity.input_type, data_type_str, count
|
|
225
|
+
)
|
|
226
|
+
|
|
220
227
|
try:
|
|
221
|
-
# Read based on input type
|
|
222
|
-
if entity.input_type
|
|
228
|
+
# Read based on input type (use string comparison for safety)
|
|
229
|
+
input_type_str = entity.input_type.value if entity.input_type else None
|
|
230
|
+
|
|
231
|
+
if input_type_str == "coil":
|
|
223
232
|
result = await self._client.read_coils(
|
|
224
|
-
entity.address, count=1,
|
|
233
|
+
entity.address, count=1, device_id=self.unit
|
|
225
234
|
)
|
|
226
235
|
if result.isError():
|
|
227
236
|
_LOGGER.warning("Error reading coil %s", entity.address)
|
|
228
237
|
return None
|
|
229
238
|
return bool(result.bits[0])
|
|
230
239
|
|
|
231
|
-
if
|
|
240
|
+
if input_type_str == "discrete_input":
|
|
232
241
|
result = await self._client.read_discrete_inputs(
|
|
233
|
-
entity.address, count=1,
|
|
242
|
+
entity.address, count=1, device_id=self.unit
|
|
234
243
|
)
|
|
235
244
|
if result.isError():
|
|
236
245
|
_LOGGER.warning("Error reading discrete input %s", entity.address)
|
|
237
246
|
return None
|
|
238
247
|
return bool(result.bits[0])
|
|
239
248
|
|
|
240
|
-
if
|
|
249
|
+
if input_type_str == "input":
|
|
241
250
|
result = await self._client.read_input_registers(
|
|
242
|
-
entity.address, count=count,
|
|
251
|
+
entity.address, count=count, device_id=self.unit
|
|
243
252
|
)
|
|
244
|
-
else: #
|
|
253
|
+
else: # holding
|
|
245
254
|
result = await self._client.read_holding_registers(
|
|
246
|
-
entity.address, count=count,
|
|
255
|
+
entity.address, count=count, device_id=self.unit
|
|
247
256
|
)
|
|
248
257
|
|
|
249
258
|
if result.isError():
|
|
@@ -253,19 +262,27 @@ class QubeClient:
|
|
|
253
262
|
regs = result.registers
|
|
254
263
|
val: float | int = 0
|
|
255
264
|
|
|
256
|
-
|
|
257
|
-
|
|
265
|
+
_LOGGER.debug(
|
|
266
|
+
"read_entity: key=%s raw_regs=%s", entity.key, regs
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# Decode based on data type (use string comparison for safety)
|
|
270
|
+
if data_type_str == "float32":
|
|
258
271
|
int_val = (regs[1] << 16) | regs[0]
|
|
259
272
|
val = struct.unpack(">f", struct.pack(">I", int_val))[0]
|
|
260
|
-
|
|
273
|
+
_LOGGER.debug(
|
|
274
|
+
"read_entity: key=%s float32 int_val=%s decoded=%s",
|
|
275
|
+
entity.key, int_val, val
|
|
276
|
+
)
|
|
277
|
+
elif data_type_str == "int16":
|
|
261
278
|
val = regs[0]
|
|
262
279
|
if val > 32767:
|
|
263
280
|
val -= 65536
|
|
264
|
-
elif
|
|
281
|
+
elif data_type_str == "uint16":
|
|
265
282
|
val = regs[0]
|
|
266
|
-
elif
|
|
283
|
+
elif data_type_str == "uint32":
|
|
267
284
|
val = (regs[1] << 16) | regs[0]
|
|
268
|
-
elif
|
|
285
|
+
elif data_type_str == "int32":
|
|
269
286
|
val = (regs[1] << 16) | regs[0]
|
|
270
287
|
if val > 2147483647:
|
|
271
288
|
val -= 4294967296
|
|
@@ -276,6 +293,11 @@ class QubeClient:
|
|
|
276
293
|
if entity.offset is not None:
|
|
277
294
|
val = val + entity.offset
|
|
278
295
|
|
|
296
|
+
_LOGGER.debug(
|
|
297
|
+
"read_entity: key=%s final_value=%s (scale=%s, offset=%s)",
|
|
298
|
+
entity.key, val, entity.scale, entity.offset
|
|
299
|
+
)
|
|
300
|
+
|
|
279
301
|
return val
|
|
280
302
|
|
|
281
303
|
except Exception as e:
|
|
@@ -381,7 +403,7 @@ class QubeClient:
|
|
|
381
403
|
|
|
382
404
|
try:
|
|
383
405
|
result = await self._client.write_coil(
|
|
384
|
-
entity.address, value,
|
|
406
|
+
entity.address, value, device_id=self.unit
|
|
385
407
|
)
|
|
386
408
|
if result.isError():
|
|
387
409
|
_LOGGER.warning("Error writing switch %s", key)
|
|
@@ -429,17 +451,17 @@ class QubeClient:
|
|
|
429
451
|
int_val = struct.unpack(">I", packed)[0]
|
|
430
452
|
regs = [int_val & 0xFFFF, (int_val >> 16) & 0xFFFF]
|
|
431
453
|
result = await self._client.write_registers(
|
|
432
|
-
entity.address, regs,
|
|
454
|
+
entity.address, regs, device_id=self.unit
|
|
433
455
|
)
|
|
434
456
|
elif entity.data_type == DataType.INT16:
|
|
435
457
|
if write_value < 0:
|
|
436
458
|
write_value = int(write_value) + 65536
|
|
437
459
|
result = await self._client.write_register(
|
|
438
|
-
entity.address, int(write_value),
|
|
460
|
+
entity.address, int(write_value), device_id=self.unit
|
|
439
461
|
)
|
|
440
462
|
elif entity.data_type == DataType.UINT16:
|
|
441
463
|
result = await self._client.write_register(
|
|
442
|
-
entity.address, int(write_value),
|
|
464
|
+
entity.address, int(write_value), device_id=self.unit
|
|
443
465
|
)
|
|
444
466
|
else:
|
|
445
467
|
_LOGGER.warning("Unsupported data type for writing: %s", entity.data_type)
|
{python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/ISSUE_TEMPLATE/bug_report.yml
RENAMED
|
File without changes
|
|
File without changes
|
{python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/ISSUE_TEMPLATE/feature_request.yml
RENAMED
|
File without changes
|
|
File without changes
|
{python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.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.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/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
|