python-qube-heatpump 1.4.3__tar.gz → 1.4.5__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.3 → python_qube_heatpump-1.4.5}/PKG-INFO +1 -1
  2. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/pyproject.toml +1 -1
  3. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/client.py +18 -34
  4. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  5. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  6. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  7. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/.github/workflows/ci.yml +0 -0
  8. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/.github/workflows/python-publish.yml +0 -0
  9. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/.gitignore +0 -0
  10. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/AGENTS.md +0 -0
  11. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/CLAUDE.md +0 -0
  12. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/LICENSE +0 -0
  13. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/README.md +0 -0
  14. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/pytest.ini +0 -0
  15. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/__init__.py +0 -0
  16. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/const.py +0 -0
  17. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/entities/__init__.py +0 -0
  18. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/entities/base.py +0 -0
  19. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/entities/binary_sensors.py +0 -0
  20. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/entities/sensors.py +0 -0
  21. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/entities/switches.py +0 -0
  22. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/models.py +0 -0
  23. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/src/python_qube_heatpump/py.typed +0 -0
  24. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/tests/conftest.py +0 -0
  25. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/tests/test_client.py +0 -0
  26. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/tests/test_const.py +0 -0
  27. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/tests/test_entities.py +0 -0
  28. {python_qube_heatpump-1.4.3 → python_qube_heatpump-1.4.5}/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
3
+ Version: 1.4.5
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.4.3"
7
+ version = "1.4.5"
8
8
  authors = [
9
9
  { name="MattieGit", email="6250046+MattieGit@users.noreply.github.com" },
10
10
  ]
@@ -162,18 +162,14 @@ class QubeClient:
162
162
  # Full 32-bit int: (Reg1 << 16) | Reg0
163
163
  # Then pack as >I (Big Endian 32-bit int) and unpack as >f (Big Endian float)?
164
164
  #
165
- # Wait, PyModbus BinaryPayloadDecoder.fromRegisters(registers, byteorder=Endian.Big, wordorder=Endian.Little)
166
- # ByteOrder Big: Normal network byte order per register.
167
- # WordOrder Little: The first register is the least significant word.
168
- #
169
- # So:
170
- # 32-bit value = (regs[1] << 16) | regs[0]
171
- # Then interpret that 32-bit integer as a float.
172
- # To interpret int bits as float in Python: struct.unpack('!f', struct.pack('!I', int_val))[0]
165
+ # Qube uses Big Endian word order (ABCD format):
166
+ # regs[0] = MSW (Most Significant Word)
167
+ # regs[1] = LSW (Least Significant Word)
168
+ # 32-bit value = (regs[0] << 16) | regs[1]
173
169
 
174
170
  if data_type == const.DataType.FLOAT32:
175
- # Combine 2 registers, Little Endian Word Order
176
- int_val = (regs[1] << 16) | regs[0]
171
+ # Combine 2 registers, Big Endian Word Order
172
+ int_val = (regs[0] << 16) | regs[1]
177
173
  val = struct.unpack(">f", struct.pack(">I", int_val))[0]
178
174
  elif data_type == const.DataType.INT16:
179
175
  val = regs[0]
@@ -183,9 +179,11 @@ class QubeClient:
183
179
  elif data_type == const.DataType.UINT16:
184
180
  val = regs[0]
185
181
  elif data_type == const.DataType.UINT32:
186
- val = (regs[1] << 16) | regs[0]
182
+ int_val = (regs[0] << 16) | regs[1]
183
+ val = int_val
187
184
  elif data_type == const.DataType.INT32:
188
- val = (regs[1] << 16) | regs[0]
185
+ int_val = (regs[0] << 16) | regs[1]
186
+ val = int_val
189
187
  if val > 2147483647:
190
188
  val -= 4294967296
191
189
  else:
@@ -219,11 +217,6 @@ class QubeClient:
219
217
  else:
220
218
  count = 1
221
219
 
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
-
227
220
  try:
228
221
  # Read based on input type (use string comparison for safety)
229
222
  input_type_str = entity.input_type.value if entity.input_type else None
@@ -262,18 +255,11 @@ class QubeClient:
262
255
  regs = result.registers
263
256
  val: float | int = 0
264
257
 
265
- _LOGGER.debug(
266
- "read_entity: key=%s raw_regs=%s", entity.key, regs
267
- )
268
-
269
258
  # Decode based on data type (use string comparison for safety)
259
+ # Qube uses big endian word order (ABCD): regs[0]=MSW, regs[1]=LSW
270
260
  if data_type_str == "float32":
271
- int_val = (regs[1] << 16) | regs[0]
261
+ int_val = (regs[0] << 16) | regs[1]
272
262
  val = struct.unpack(">f", struct.pack(">I", int_val))[0]
273
- _LOGGER.debug(
274
- "read_entity: key=%s float32 int_val=%s decoded=%s",
275
- entity.key, int_val, val
276
- )
277
263
  elif data_type_str == "int16":
278
264
  val = regs[0]
279
265
  if val > 32767:
@@ -281,9 +267,11 @@ class QubeClient:
281
267
  elif data_type_str == "uint16":
282
268
  val = regs[0]
283
269
  elif data_type_str == "uint32":
284
- val = (regs[1] << 16) | regs[0]
270
+ int_val = (regs[0] << 16) | regs[1]
271
+ val = int_val
285
272
  elif data_type_str == "int32":
286
- val = (regs[1] << 16) | regs[0]
273
+ int_val = (regs[0] << 16) | regs[1]
274
+ val = int_val
287
275
  if val > 2147483647:
288
276
  val -= 4294967296
289
277
 
@@ -293,11 +281,6 @@ class QubeClient:
293
281
  if entity.offset is not None:
294
282
  val = val + entity.offset
295
283
 
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
-
301
284
  return val
302
285
 
303
286
  except Exception as e:
@@ -447,9 +430,10 @@ class QubeClient:
447
430
  # Encode based on data type
448
431
  if entity.data_type == DataType.FLOAT32:
449
432
  # Pack as big-endian float, then split into two registers
433
+ # Big Endian word order: regs[0]=MSW, regs[1]=LSW
450
434
  packed = struct.pack(">f", write_value)
451
435
  int_val = struct.unpack(">I", packed)[0]
452
- regs = [int_val & 0xFFFF, (int_val >> 16) & 0xFFFF]
436
+ regs = [(int_val >> 16) & 0xFFFF, int_val & 0xFFFF]
453
437
  result = await self._client.write_registers(
454
438
  entity.address, regs, device_id=self.unit
455
439
  )