python-qube-heatpump 1.2.1__py3-none-any.whl → 1.2.3__py3-none-any.whl

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.
@@ -1,11 +1,10 @@
1
1
  """Client for Qube Heat Pump."""
2
2
 
3
3
  import logging
4
+ import struct
4
5
  from typing import Optional
5
6
 
6
7
  from pymodbus.client import AsyncModbusTcpClient
7
- from pymodbus.payload import BinaryPayloadDecoder
8
- from pymodbus.constants import Endian
9
8
 
10
9
  from . import const
11
10
  from .models import QubeState
@@ -47,11 +46,33 @@ class QubeClient:
47
46
  async def _read(const_def):
48
47
  return await self.read_value(const_def)
49
48
 
50
- # Fetch basic sensors
49
+ # Fetch temperature sensors
51
50
  state.temp_supply = await _read(const.TEMP_SUPPLY)
52
51
  state.temp_return = await _read(const.TEMP_RETURN)
53
- state.temp_outside = await _read(const.TEMP_OUTSIDE)
52
+ state.temp_source_in = await _read(const.TEMP_SOURCE_IN)
53
+ state.temp_source_out = await _read(const.TEMP_SOURCE_OUT)
54
+ state.temp_room = await _read(const.TEMP_ROOM)
54
55
  state.temp_dhw = await _read(const.TEMP_DHW)
56
+ state.temp_outside = await _read(const.TEMP_OUTSIDE)
57
+
58
+ # Fetch power and energy sensors
59
+ state.power_thermic = await _read(const.POWER_THERMIC)
60
+ state.power_electric = await _read(const.POWER_ELECTRIC_CALC)
61
+ state.energy_total_electric = await _read(const.ENERGY_ELECTRIC_TOTAL)
62
+ state.energy_total_thermic = await _read(const.ENERGY_THERMIC_TOTAL)
63
+ state.cop_calc = await _read(const.COP_CALC)
64
+
65
+ # Fetch operation sensors
66
+ state.status_code = await _read(const.STATUS_CODE)
67
+ state.compressor_speed = await _read(const.COMPRESSOR_SPEED)
68
+ state.flow_rate = await _read(const.FLOW_RATE)
69
+
70
+ # Fetch setpoints (holding registers)
71
+ state.setpoint_room_heat_day = await _read(const.SETPOINT_HEAT_DAY)
72
+ state.setpoint_room_heat_night = await _read(const.SETPOINT_HEAT_NIGHT)
73
+ state.setpoint_room_cool_day = await _read(const.SETPOINT_COOL_DAY)
74
+ state.setpoint_room_cool_night = await _read(const.SETPOINT_COOL_NIGHT)
75
+ state.setpoint_dhw = await _read(const.USER_DHW_SETPOINT)
55
76
 
56
77
  return state
57
78
 
@@ -80,16 +101,48 @@ class QubeClient:
80
101
  _LOGGER.warning("Error reading address %s", address)
81
102
  return None
82
103
 
83
- decoder = BinaryPayloadDecoder.fromRegisters(
84
- result.registers, byteorder=Endian.Big, wordorder=Endian.Little
85
- )
104
+ regs = result.registers
105
+ val = 0
106
+
107
+ # Manual decoding to avoid pymodbus.payload dependencies
108
+ # Assuming Little Endian Word Order for 32-bit values [LSW, MSW] per standard Modbus often used
109
+ # But the original code used Endian.Little WordOrder.
110
+ # Decoder: byteorder=Endian.Big, wordorder=Endian.Little
111
+ # Big Endian Bytes: [H, L]
112
+ # Little Endian Words: [Reg0, Reg1] -> [LSW, MSW]
113
+ #
114
+ # Example Float32: 123.456
115
+ # Reg0 (LSW)
116
+ # Reg1 (MSW)
117
+ # Full 32-bit int: (Reg1 << 16) | Reg0
118
+ # Then pack as >I (Big Endian 32-bit int) and unpack as >f (Big Endian float)?
119
+ #
120
+ # Wait, PyModbus BinaryPayloadDecoder.fromRegisters(registers, byteorder=Endian.Big, wordorder=Endian.Little)
121
+ # ByteOrder Big: Normal network byte order per register.
122
+ # WordOrder Little: The first register is the least significant word.
123
+ #
124
+ # So:
125
+ # 32-bit value = (regs[1] << 16) | regs[0]
126
+ # Then interpret that 32-bit integer as a float.
127
+ # To interpret int bits as float in Python: struct.unpack('!f', struct.pack('!I', int_val))[0]
86
128
 
87
129
  if data_type == const.DataType.FLOAT32:
88
- val = decoder.decode_32bit_float()
130
+ # Combine 2 registers, Little Endian Word Order
131
+ int_val = (regs[1] << 16) | regs[0]
132
+ val = struct.unpack(">f", struct.pack(">I", int_val))[0]
89
133
  elif data_type == const.DataType.INT16:
90
- val = decoder.decode_16bit_int()
134
+ val = regs[0]
135
+ # Signed 16-bit
136
+ if val > 32767:
137
+ val -= 65536
91
138
  elif data_type == const.DataType.UINT16:
92
- val = decoder.decode_16bit_uint()
139
+ val = regs[0]
140
+ elif data_type == const.DataType.UINT32:
141
+ val = (regs[1] << 16) | regs[0]
142
+ elif data_type == const.DataType.INT32:
143
+ val = (regs[1] << 16) | regs[0]
144
+ if val > 2147483647:
145
+ val -= 4294967296
93
146
  else:
94
147
  val = 0
95
148
 
@@ -16,6 +16,8 @@ class DataType(str, Enum):
16
16
  FLOAT32 = "float32"
17
17
  INT16 = "int16"
18
18
  UINT16 = "uint16"
19
+ INT32 = "int32"
20
+ UINT32 = "uint32"
19
21
 
20
22
 
21
23
  # Register definitions (Address, Type, Data Type, Scale, Offset)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-qube-heatpump
3
- Version: 1.2.1
3
+ Version: 1.2.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
@@ -0,0 +1,8 @@
1
+ python_qube_heatpump/__init__.py,sha256=eW8_tyAweg7YTOI599pi8gf3mt7aXW0SCw5ZyrBVJpU,57
2
+ python_qube_heatpump/client.py,sha256=BgCJbQBV57cfsWMfakjbs2VXgrQ8BZH8KnX1pnTke7k,6083
3
+ python_qube_heatpump/const.py,sha256=sXvXRcDb1uvBgzH2lV67Me_XtUErKA3fXMLO9gEGrlQ,3680
4
+ python_qube_heatpump/models.py,sha256=3I5U9_rEe1r73hwY4sNAMXfIxyPjBOtx06c_mAURLDk,1141
5
+ python_qube_heatpump-1.2.3.dist-info/METADATA,sha256=P-_IjdAl1jsiU4xYN_6oqlYK6gPvN8mvxM3qwU5tGmY,950
6
+ python_qube_heatpump-1.2.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
7
+ python_qube_heatpump-1.2.3.dist-info/licenses/LICENSE,sha256=qpuQXN7QwpILG9GYcmqrd3Ax5CxBZUBoT295xTgKnOM,1062
8
+ python_qube_heatpump-1.2.3.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- python_qube_heatpump/__init__.py,sha256=eW8_tyAweg7YTOI599pi8gf3mt7aXW0SCw5ZyrBVJpU,57
2
- python_qube_heatpump/client.py,sha256=XNVCydP6uKIlUbH28FjcA9oXYumNRy5NBCqPrVMCX60,3360
3
- python_qube_heatpump/const.py,sha256=bAFNIN8uwXIdQ5VGgSYdFrQYUNDcDXlxr0OkBxlKUYw,3638
4
- python_qube_heatpump/models.py,sha256=3I5U9_rEe1r73hwY4sNAMXfIxyPjBOtx06c_mAURLDk,1141
5
- python_qube_heatpump-1.2.1.dist-info/METADATA,sha256=nqZty88ZKHR7RvM4F1TsxsuFpQoBetXHva29iOv8n1Q,950
6
- python_qube_heatpump-1.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
7
- python_qube_heatpump-1.2.1.dist-info/licenses/LICENSE,sha256=qpuQXN7QwpILG9GYcmqrd3Ax5CxBZUBoT295xTgKnOM,1062
8
- python_qube_heatpump-1.2.1.dist-info/RECORD,,