python-qube-heatpump 1.3.0__tar.gz → 1.4.0__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.3.0 → python_qube_heatpump-1.4.0}/PKG-INFO +1 -1
  2. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/pyproject.toml +1 -1
  3. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/src/python_qube_heatpump/client.py +55 -14
  4. python_qube_heatpump-1.4.0/src/python_qube_heatpump/py.typed +0 -0
  5. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  6. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  7. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  8. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/.github/workflows/ci.yml +0 -0
  9. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/.github/workflows/python-publish.yml +0 -0
  10. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/.gitignore +0 -0
  11. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/AGENTS.md +0 -0
  12. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/CLAUDE.md +0 -0
  13. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/LICENSE +0 -0
  14. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/README.md +0 -0
  15. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/pytest.ini +0 -0
  16. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/src/python_qube_heatpump/__init__.py +0 -0
  17. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/src/python_qube_heatpump/const.py +0 -0
  18. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/src/python_qube_heatpump/entities/__init__.py +0 -0
  19. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/src/python_qube_heatpump/entities/base.py +0 -0
  20. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/src/python_qube_heatpump/entities/binary_sensors.py +0 -0
  21. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/src/python_qube_heatpump/entities/sensors.py +0 -0
  22. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/src/python_qube_heatpump/entities/switches.py +0 -0
  23. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/src/python_qube_heatpump/models.py +0 -0
  24. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/tests/conftest.py +0 -0
  25. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/tests/test_client.py +0 -0
  26. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/tests/test_const.py +0 -0
  27. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/tests/test_entities.py +0 -0
  28. {python_qube_heatpump-1.3.0 → python_qube_heatpump-1.4.0}/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.0
3
+ Version: 1.4.0
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.3.0"
7
+ version = "1.4.0"
8
8
  authors = [
9
9
  { name="MattieGit", email="6250046+MattieGit@users.noreply.github.com" },
10
10
  ]
@@ -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, slave=self.unit
138
+ address, count, device_id=self.unit
98
139
  )
99
140
  else:
100
141
  result = await self._client.read_holding_registers(
101
- address, count, slave=self.unit
142
+ address, count, device_id=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, slave=self.unit
224
+ entity.address, count=1, device_id=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, slave=self.unit
233
+ entity.address, count=1, device_id=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, slave=self.unit
242
+ entity.address, count, device_id=self.unit
202
243
  )
203
244
  else: # HOLDING_REGISTER
204
245
  result = await self._client.read_holding_registers(
205
- entity.address, count, slave=self.unit
246
+ entity.address, count, device_id=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, slave=self.unit
384
+ entity.address, value, device_id=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, slave=self.unit
432
+ entity.address, regs, device_id=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), slave=self.unit
438
+ entity.address, int(write_value), device_id=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), slave=self.unit
442
+ entity.address, int(write_value), device_id=self.unit
402
443
  )
403
444
  else:
404
445
  _LOGGER.warning("Unsupported data type for writing: %s", entity.data_type)