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.
Files changed (28) hide show
  1. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/PKG-INFO +2 -2
  2. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/pyproject.toml +2 -2
  3. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/client.py +44 -22
  4. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  5. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  6. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  7. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/workflows/ci.yml +0 -0
  8. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.github/workflows/python-publish.yml +0 -0
  9. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/.gitignore +0 -0
  10. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/AGENTS.md +0 -0
  11. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/CLAUDE.md +0 -0
  12. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/LICENSE +0 -0
  13. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/README.md +0 -0
  14. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/pytest.ini +0 -0
  15. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/__init__.py +0 -0
  16. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/const.py +0 -0
  17. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/__init__.py +0 -0
  18. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/base.py +0 -0
  19. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/binary_sensors.py +0 -0
  20. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/sensors.py +0 -0
  21. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/entities/switches.py +0 -0
  22. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/models.py +0 -0
  23. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/src/python_qube_heatpump/py.typed +0 -0
  24. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/tests/conftest.py +0 -0
  25. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/tests/test_client.py +0 -0
  26. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/tests/test_const.py +0 -0
  27. {python_qube_heatpump-1.4.1 → python_qube_heatpump-1.4.3}/tests/test_entities.py +0 -0
  28. {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.1
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.6.0
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.1"
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.6.0",
20
+ "pymodbus>=3.11.0",
21
21
  ]
22
22
 
23
23
  [project.optional-dependencies]
@@ -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, slave=self.unit
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, slave=self.unit
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
- if entity.data_type in (DataType.FLOAT32, DataType.UINT32, DataType.INT32):
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 == InputType.COIL:
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, slave=self.unit
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 entity.input_type == InputType.DISCRETE_INPUT:
240
+ if input_type_str == "discrete_input":
232
241
  result = await self._client.read_discrete_inputs(
233
- entity.address, count=1, slave=self.unit
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 entity.input_type == InputType.INPUT_REGISTER:
249
+ if input_type_str == "input":
241
250
  result = await self._client.read_input_registers(
242
- entity.address, count=count, slave=self.unit
251
+ entity.address, count=count, device_id=self.unit
243
252
  )
244
- else: # HOLDING_REGISTER
253
+ else: # holding
245
254
  result = await self._client.read_holding_registers(
246
- entity.address, count=count, slave=self.unit
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
- # Decode based on data type
257
- if entity.data_type == DataType.FLOAT32:
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
- elif entity.data_type == DataType.INT16:
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 entity.data_type == DataType.UINT16:
281
+ elif data_type_str == "uint16":
265
282
  val = regs[0]
266
- elif entity.data_type == DataType.UINT32:
283
+ elif data_type_str == "uint32":
267
284
  val = (regs[1] << 16) | regs[0]
268
- elif entity.data_type == DataType.INT32:
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, slave=self.unit
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, slave=self.unit
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), slave=self.unit
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), slave=self.unit
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)