Skip to content

Commit c2d4299

Browse files
committed
* Fixed SystemairSerialClient support for latest pymodbus
1 parent 3b260c7 commit c2d4299

File tree

2 files changed

+41
-53
lines changed

2 files changed

+41
-53
lines changed

custom_components/systemair/api.py

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,14 @@ async def _execute_request(self, request_type: str, address: int, **kwargs: Any)
182182
await self._ensure_connected()
183183

184184
if request_type == "read":
185-
result = await self._client.read_holding_registers(address=address, count=kwargs["count"], device_id=self.slave_id)
185+
count = kwargs.get("count", 1)
186+
result = await self._client.read_holding_registers(address=address, count=count, device_id=self.slave_id)
186187
elif request_type == "write":
187-
result = await self._client.write_register(address=address, value=kwargs["value"], device_id=self.slave_id)
188+
value = kwargs["value"]
189+
result = await self._client.write_register(address=address, value=value, device_id=self.slave_id)
188190
elif request_type == "write_multiple":
189-
result = await self._client.write_registers(address=address, values=kwargs["values"], device_id=self.slave_id)
191+
values = kwargs["values"]
192+
result = await self._client.write_registers(address=address, values=values, device_id=self.slave_id)
190193
else:
191194
self._raise_unknown_request_type(request_type)
192195

@@ -400,30 +403,30 @@ async def _execute_request(self, request_type: str, address: int, **kwargs: Any)
400403

401404
if request_type == "read":
402405
count = kwargs.get("count", 1)
403-
result = await self._client.read_holding_registers(address, count, slave=self._slave_id)
406+
result = await self._client.read_holding_registers(address=address, count=count, device_id=self._slave_id)
404407
elif request_type == "write":
405408
value = kwargs["value"]
406-
result = await self._client.write_register(address, value, slave=self._slave_id)
409+
result = await self._client.write_register(address=address, value=value, device_id=self._slave_id)
407410
elif request_type == "write_multiple":
408411
values = kwargs["values"]
409-
result = await self._client.write_registers(address, values, slave=self._slave_id)
412+
result = await self._client.write_registers(address=address, values=values, device_id=self._slave_id)
410413
else:
411414
self._raise_unknown_request_type(request_type)
412415

413-
if result.isError():
414-
exception_code = getattr(result, "exception_code", None)
415-
if exception_code in {MODBUS_DEVICE_BUSY_EXCEPTION, MODBUS_GATEWAY_TARGET_FAILED_TO_RESPOND}:
416-
LOGGER.debug(
417-
"Device busy/unresponsive (code %s) on %s. Retrying in %.2fs...",
418-
result.exception_code,
419-
request_type,
420-
delay,
421-
)
422-
await asyncio.sleep(delay)
423-
else:
424-
self._raise_unrecoverable_modbus_error(result)
416+
if not result.isError():
417+
return result.registers if request_type == "read" else True
418+
419+
if result.exception_code in {MODBUS_DEVICE_BUSY_EXCEPTION, MODBUS_GATEWAY_TARGET_FAILED_TO_RESPOND}:
420+
delay = base_delay * (2**attempt)
421+
LOGGER.debug(
422+
"Device busy/unresponsive (code %s) on %s. Retrying in %.2fs...",
423+
result.exception_code,
424+
request_type,
425+
delay,
426+
)
427+
await asyncio.sleep(delay)
425428
else:
426-
return result
429+
self._raise_unrecoverable_modbus_error(result)
427430

428431
except (TimeoutError, ConnectionException, ModbusConnectionError) as e:
429432
LOGGER.warning("Connection error during %s: %s. Attempting to reconnect...", request_type, e)
@@ -466,26 +469,21 @@ async def _queue_request(self, request_type: str, address: int, **kwargs: Any) -
466469

467470
async def write_register(self, address_1based: int, value: int) -> None:
468471
"""Queue a write request for a single holding register."""
469-
result = await self._queue_request("write", address_1based - 1, value=value)
470-
if result.isError():
471-
msg = f"Failed to write register {address_1based}"
472-
raise ModbusConnectionError(msg)
472+
await self._queue_request("write", address_1based - 1, value=value)
473473

474474
async def write_registers_32bit(self, address_1based: int, value: int) -> None:
475475
"""Queue a write request for a 32-bit value across two registers."""
476476
low_word = value & 0xFFFF
477477
high_word = (value >> 16) & 0xFFFF
478-
result = await self._queue_request("write_multiple", address_1based - 1, values=[low_word, high_word])
479-
if result.isError():
480-
msg = f"Failed to write 32-bit value to registers {address_1based}-{address_1based + 1}"
481-
raise ModbusConnectionError(msg)
478+
values = [low_word, high_word]
479+
await self._queue_request("write_multiple", address_1based - 1, values=values)
482480

483481
async def test_connection(self) -> bool:
484482
"""Test connection to the Modbus Serial device."""
485483
try:
486484
await self._ensure_connection()
487485
# Try to read a single register to verify communication
488-
result = await self._client.read_holding_registers(0, 1, slave=self._slave_id)
486+
result = await self._client.read_holding_registers(address=0, count=1, device_id=self._slave_id)
489487
return not result.isError()
490488
except (ModbusConnectionError, ConnectionException) as e:
491489
LOGGER.error("Serial connection test failed: %s", e)
@@ -495,34 +493,24 @@ async def test_connection(self) -> bool:
495493
return False
496494

497495
async def get_all_data(self) -> dict[str, Any]:
498-
"""Get all data from device by reading all defined register blocks."""
499-
all_registers: dict[str, Any] = {}
500-
has_successful_read = False
501-
502-
for start_address_1based, count in READ_BLOCKS:
503-
try:
504-
result = await self._queue_request("read", start_address_1based - 1, count=count)
505-
506-
if result.isError():
507-
LOGGER.debug("Failed to read block at %d: error", start_address_1based)
508-
continue
509-
510-
has_successful_read = True
511-
registers = result.registers
496+
"""Queue read requests for all required data blocks and assemble the result."""
497+
tasks = [self._queue_request("read", address=start - 1, count=count) for start, count in READ_BLOCKS]
512498

513-
# Map register values to parameter names
514-
for reg_addr in range(start_address_1based, start_address_1based + count):
515-
key = str(reg_addr)
516-
reg_val = registers[reg_addr - start_address_1based]
517-
all_registers[key] = reg_val
499+
results = await asyncio.gather(*tasks, return_exceptions=True)
518500

519-
except ModbusConnectionError as e:
520-
LOGGER.debug("Error reading block at %d: %s", start_address_1based, e)
521-
continue
522-
except (TimeoutError, ConnectionException) as e:
523-
LOGGER.debug("Connection error reading block at %d: %s", start_address_1based, e)
501+
all_registers = {}
502+
has_successful_read = False
503+
for i, result in enumerate(results):
504+
start_addr_1based, _ = READ_BLOCKS[i]
505+
if isinstance(result, Exception):
506+
LOGGER.error(f"Failed to read block {start_addr_1based}: {result}")
524507
continue
525508

509+
has_successful_read = True
510+
for offset, reg_val in enumerate(result):
511+
key = str(start_addr_1based - 1 + offset)
512+
all_registers[key] = reg_val
513+
526514
if not has_successful_read:
527515
msg = "Failed to read any data blocks from the device."
528516
raise ModbusConnectionError(msg)

custom_components/systemair/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@
1515
"aiohttp",
1616
"async-timeout"
1717
],
18-
"version": "1.0.10"
18+
"version": "1.0.11"
1919
}

0 commit comments

Comments
 (0)