Skip to content

Commit

Permalink
Merge branch 'main' into update-options-flow
Browse files Browse the repository at this point in the history
  • Loading branch information
WillCodeForCats committed Dec 20, 2024
2 parents ba9428a + 5691b56 commit 9b6ca72
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 19 deletions.
20 changes: 20 additions & 0 deletions custom_components/solaredge_modbus_multi/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""

Expand Down
42 changes: 24 additions & 18 deletions custom_components/solaredge_modbus_multi/hub.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import asyncio
import importlib.metadata
import logging
from collections import OrderedDict

Expand All @@ -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,
Expand All @@ -28,13 +25,15 @@
ConfDefaultStr,
ConfName,
ModbusDefaults,
ModbusExceptions,
RetrySettings,
SolarEdgeTimeouts,
SunSpecNotImpl,
)
from .helpers import float_to_hex, parse_modbus_string

_LOGGER = logging.getLogger(__name__)
pymodbus_version = importlib.metadata.version("pymodbus")


class SolarEdgeException(Exception):
Expand Down Expand Up @@ -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."""

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}."
)
Expand Down
2 changes: 1 addition & 1 deletion custom_components/solaredge_modbus_multi/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}

0 comments on commit 9b6ca72

Please sign in to comment.