diff --git a/custom_components/solaredge_modbus_multi/const.py b/custom_components/solaredge_modbus_multi/const.py index 91b8c4d4..1f007271 100644 --- a/custom_components/solaredge_modbus_multi/const.py +++ b/custom_components/solaredge_modbus_multi/const.py @@ -28,6 +28,26 @@ ) +class ModbusExceptions: + """An enumeration of the valid modbus exceptions.""" + + """ + Copied from pymodbus source: + https://github.com/pymodbus-dev/pymodbus/blob/a1c14c7a8fbea52618ba1cbc9933c1dd24c3339d/pymodbus/pdu/pdu.py#L72 + """ + + IllegalFunction = 0x01 + IllegalAddress = 0x02 + IllegalValue = 0x03 + SlaveFailure = 0x04 + Acknowledge = 0x05 + SlaveBusy = 0x06 + NegativeAcknowledge = 0x07 + MemoryParityError = 0x08 + GatewayPathUnavailable = 0x0A + GatewayNoResponse = 0x0B + + class RetrySettings(IntEnum): """Retry settings when opening a connection to the inverter fails.""" diff --git a/custom_components/solaredge_modbus_multi/hub.py b/custom_components/solaredge_modbus_multi/hub.py index 77fe99d3..f7808a38 100644 --- a/custom_components/solaredge_modbus_multi/hub.py +++ b/custom_components/solaredge_modbus_multi/hub.py @@ -1,6 +1,7 @@ from __future__ import annotations import asyncio +import importlib.metadata import logging from collections import OrderedDict @@ -9,15 +10,11 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import issue_registry as ir from homeassistant.helpers.entity import DeviceInfo - -try: - from pymodbus.client import AsyncModbusTcpClient - from pymodbus.constants import Endian - from pymodbus.exceptions import ConnectionException, ModbusIOException - from pymodbus.payload import BinaryPayloadDecoder - from pymodbus.pdu import ExceptionResponse, ModbusExceptions -except ImportError: - raise ImportError("pymodbus is not installed, or pymodbus version is not supported") +from pymodbus.client import AsyncModbusTcpClient +from pymodbus.constants import Endian +from pymodbus.exceptions import ConnectionException, ModbusIOException +from pymodbus.payload import BinaryPayloadDecoder +from pymodbus.pdu import ExceptionResponse from .const import ( BATTERY_REG_BASE, @@ -28,6 +25,7 @@ ConfDefaultStr, ConfName, ModbusDefaults, + ModbusExceptions, RetrySettings, SolarEdgeTimeouts, SunSpecNotImpl, @@ -35,6 +33,7 @@ from .helpers import float_to_hex, parse_modbus_string _LOGGER = logging.getLogger(__name__) +pymodbus_version = importlib.metadata.version("pymodbus") class SolarEdgeException(Exception): @@ -197,6 +196,8 @@ def __init__( ), ) + _LOGGER.debug(f"pymodbus version {pymodbus_version}") + async def _async_init_solaredge(self) -> None: """Detect devices and load initial modbus data from inverters.""" @@ -501,26 +502,26 @@ async def modbus_read_holding_registers(self, unit, address, rcount): self._rr_address = address self._rr_count = rcount - kwargs = {"slave": self._rr_unit} if self._rr_unit else {} - result = await self._client.read_holding_registers( - self._rr_address, self._rr_count, **kwargs + self._rr_address, count=self._rr_count, slave=self._rr_unit ) if result.isError(): - _LOGGER.debug(f"Unit {unit}: {result}") if type(result) is ModbusIOException: raise ModbusIOError(result) if type(result) is ExceptionResponse: if result.exception_code == ModbusExceptions.IllegalAddress: + _LOGGER.debug(f"Unit {unit} Read IllegalAddress: {result}") raise ModbusIllegalAddress(result) if result.exception_code == ModbusExceptions.IllegalFunction: + _LOGGER.debug(f"Unit {unit} Read IllegalFunction: {result}") raise ModbusIllegalFunction(result) if result.exception_code == ModbusExceptions.IllegalValue: + _LOGGER.debug(f"Unit {unit} Read IllegalValue: {result}") raise ModbusIllegalValue(result) raise ModbusReadError(result) @@ -552,9 +553,8 @@ async def write_registers(self, unit: int, address: int, payload) -> None: if not self.is_connected: await self.connect() - kwargs = {"slave": self._wr_unit} if self._wr_unit else {} result = await self._client.write_registers( - self._wr_address, self._wr_payload, **kwargs + self._wr_address, slave=self._wr_unit, values=self._wr_payload ) self.has_write = address @@ -595,19 +595,25 @@ async def write_registers(self, unit: int, address: int, payload) -> None: if type(result) is ExceptionResponse: if result.exception_code == ModbusExceptions.IllegalAddress: - _LOGGER.debug(f"Write IllegalAddress: {result}") + _LOGGER.debug( + f"Unit {self._wr_unit} Write IllegalAddress: {result}" + ) raise HomeAssistantError( "Address not supported at device at ID {self._wr_unit}." ) if result.exception_code == ModbusExceptions.IllegalFunction: - _LOGGER.debug(f"Write IllegalFunction: {result}") + _LOGGER.debug( + f"Unit {self._wr_unit} Write IllegalFunction: {result}" + ) raise HomeAssistantError( "Function not supported by device at ID {self._wr_unit}." ) if result.exception_code == ModbusExceptions.IllegalValue: - _LOGGER.debug(f"Write IllegalValue: {result}") + _LOGGER.debug( + f"Unit {self._wr_unit} Write IllegalValue: {result}" + ) raise HomeAssistantError( "Value invalid for device at ID {self._wr_unit}." ) diff --git a/custom_components/solaredge_modbus_multi/manifest.json b/custom_components/solaredge_modbus_multi/manifest.json index af68c3c8..971a81cd 100644 --- a/custom_components/solaredge_modbus_multi/manifest.json +++ b/custom_components/solaredge_modbus_multi/manifest.json @@ -10,5 +10,5 @@ "issue_tracker": "https://github.com/WillCodeForCats/solaredge-modbus-multi/issues", "loggers": ["custom_components.solaredge_modbus_multi"], "requirements": ["pymodbus>=3.6.6,<3.8"], - "version": "3.0.3" + "version": "3.0.4" }