Skip to content

Commit

Permalink
WIP getting to the bottom of all of the random errors...
Browse files Browse the repository at this point in the history
  • Loading branch information
canton7 committed Jan 22, 2025
1 parent 969094e commit 45d3c0a
Show file tree
Hide file tree
Showing 21 changed files with 39 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ repos:
# These are duplicated from requirements.txt
additional_dependencies:
[
homeassistant-stubs==2025.1.0,
homeassistant-stubs==2025.1.1,
types-python-slugify==8.0.0.2,
voluptuous-stubs==0.1.1,
]
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def connect(self) -> bool:
# https://github.com/nathanmarlor/foxess_modbus/issues/275
def recv(self, size: int | None) -> bytes:
"""Read data from the underlying descriptor."""
super(ModbusTcpClient, self).recv(size)
super(ModbusTcpClient, self).recv(size) # type: ignore
if not self.socket:
raise ConnectionException(str(self))

Expand Down Expand Up @@ -73,9 +73,7 @@ def recv(self, size: int | None) -> bytes:
# We expect a single-element list if this succeeds, or an empty list if it timed out
if len(poll_res) > 0:
if (recv_data := self.socket.recv(recv_size)) == b"":
return self._handle_abrupt_socket_close( # type: ignore[no-any-return]
size, data, time.time() - time_
)
return self._handle_abrupt_socket_close(size, data, time.time() - time_)
data.append(recv_data)
data_length += len(recv_data)
time_ = time.time()
Expand Down
5 changes: 2 additions & 3 deletions custom_components/foxess_modbus/client/modbus_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from typing import Callable
from typing import Type
from typing import TypeVar
from typing import cast

import serial
from homeassistant.core import HomeAssistant
Expand Down Expand Up @@ -152,7 +151,7 @@ async def read_registers(
response,
)

return cast(list[int], response.registers)
return response.registers

async def write_registers(self, register_address: int, register_values: list[int], slave: int) -> None:
"""Write registers"""
Expand Down Expand Up @@ -199,7 +198,7 @@ async def write_registers(self, register_address: int, register_values: list[int
async def _async_pymodbus_call(self, call: Callable[..., T], *args: Any, auto_connect: bool = True) -> T:
"""Convert async to sync pymodbus call."""

def _call() -> T:
def _call(_: Any) -> T:
# When using pollserial://, connected calls into serial.serial_for_url, which calls importlib.import_module,
# which HA doesn't like (see https://github.com/nathanmarlor/foxess_modbus/issues/618).
# Therefore we need to do this check inside the executor job
Expand Down
4 changes: 2 additions & 2 deletions custom_components/foxess_modbus/entities/entity_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import Sequence

from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity import EntityDescription
from homeassistant.util.frozen_dataclass_compat import FrozenOrThawed

from ..common.entity_controller import EntityController
from ..common.types import Inv
Expand All @@ -19,7 +19,7 @@
# We need to combine EntityDescription's metaclass with ABC's metaclass, see
# https://github.com/nathanmarlor/foxess_modbus/issues/480. This is to allow HA to move to frozen entity descriptions
# (to aid caching), and will start logging deprecation warnings in 2024.x.
class EntityFactoryMetaclass(type(EntityDescription), type(ABC)): # type: ignore
class EntityFactoryMetaclass(FrozenOrThawed, type(ABC)): # type: ignore
"""
Metaclass to use for EntityFactory.
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusBatterySensorDescription(ModbusSensorDescription):
class ModbusBatterySensorDescription(ModbusSensorDescription): # type: ignore[misc]
"""Description for ModbusBatterySensor"""

bms_connect_state_address: list[ModbusAddressSpec]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusBinarySensorDescription(BinarySensorEntityDescription, EntityFactory):
class ModbusBinarySensorDescription(BinarySensorEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Description for ModbusBinarySensor"""

address: list[InverterModelSpec]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def _is_force_charge_enabled(


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusChargePeriodStartEndSensorDescription(SensorEntityDescription, EntityFactory):
class ModbusChargePeriodStartEndSensorDescription(SensorEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Entity description for ModbusChargePeriodStartEndSensor"""

address: list[InverterModelSpec]
Expand Down Expand Up @@ -187,7 +187,9 @@ def addresses(self) -> list[int]:


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusEnableForceChargeSensorDescription(BinarySensorEntityDescription, EntityFactory):
class ModbusEnableForceChargeSensorDescription( # type ignore[misc, override]
BinarySensorEntityDescription, EntityFactory
):
"""Entity description for ModbusEnableForceChargeSensor"""

period_start_address: list[InverterModelSpec]
Expand Down
16 changes: 9 additions & 7 deletions custom_components/foxess_modbus/entities/modbus_entity_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

from homeassistant.const import Platform
from homeassistant.helpers import entity_registry
from homeassistant.helpers.entity import ABCCachedProperties
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity import Entity
from propcache import cached_property

from ..common.entity_controller import EntityController
from ..common.entity_controller import ModbusControllerEntity
Expand Down Expand Up @@ -67,18 +69,18 @@ class ModbusEntityProtocol(Protocol):
_controller: EntityController


# HA introduced a ABCCachedProperties metaclass which is used by Entity, and which derives from ABCMeta.
# This conflicts with Protocol's metaclass (from ModbusEntityProtocol).
class ModbusEntityMixinMetaclass(ABCCachedProperties, type(Protocol)): # type: ignore
pass


if TYPE_CHECKING:
_ModbusEntityMixinBase = Entity
else:
_ModbusEntityMixinBase = object


# HA introduced a ABCCachedProperties metaclass which is used by Entity, and which derives from ABCMeta.
# This conflicts with Protocol's metaclass (from ModbusEntityProtocol).
class ModbusEntityMixinMetaclass(type(Entity), type(Protocol)): # type: ignore
pass


class ModbusEntityMixin(
ModbusControllerEntity, ModbusEntityProtocol, _ModbusEntityMixinBase, metaclass=ModbusEntityMixinMetaclass
):
Expand All @@ -88,7 +90,7 @@ class ModbusEntityMixin(
This provides properties which are common to all FoxESS entities.
"""

@property
@cached_property
def unique_id(self) -> str:
"""Return a unique ID."""
return _create_unique_id(self.entity_description.key, self._controller.inverter_details)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def __post_init__(self) -> None:


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusFaultSensorDescription(SensorEntityDescription, EntityFactory):
class ModbusFaultSensorDescription(SensorEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Description for ModbusFaultSensor"""

addresses: list[ModbusAddressesSpec]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusIntegrationSensorDescription(SensorEntityDescription, EntityFactory):
class ModbusIntegrationSensorDescription(SensorEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Custom sensor description"""

models: list[EntitySpec]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusInverterStateSensorDescription(SensorEntityDescription, EntityFactory):
class ModbusInverterStateSensorDescription(SensorEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Description for ModbusInverterStateSensor"""

address: list[ModbusAddressSpec]
Expand Down Expand Up @@ -104,7 +104,7 @@ def addresses(self) -> list[int]:


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusG2InverterStateSensorDescription(SensorEntityDescription, EntityFactory):
class ModbusG2InverterStateSensorDescription(SensorEntityDescription, EntityFactory): # type ignore[override]
"""Description for ModbusInverterStateSensor"""

# Fault 1 code, fault 3 code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusLambdaSensorDescription(SensorEntityDescription, EntityFactory):
class ModbusLambdaSensorDescription(SensorEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Entity description for ModbusLambdaSensors"""

models: list[EntitySpec]
Expand Down
2 changes: 1 addition & 1 deletion custom_components/foxess_modbus/entities/modbus_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusNumberDescription(NumberEntityDescription, EntityFactory):
class ModbusNumberDescription(NumberEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Custom number entity description"""

address: list[ModbusAddressSpec]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusRemoteControlNumberDescription(NumberEntityDescription, EntityFactory):
class ModbusRemoteControlNumberDescription(NumberEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Custom number entity description"""

models: list[EntitySpec]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusRemoteControlSelectDescription(SelectEntityDescription, EntityFactory):
class ModbusRemoteControlSelectDescription(SelectEntityDescription, EntityFactory): # type: ignore[misc]
models: list[EntitySpec]

@property
Expand Down
2 changes: 1 addition & 1 deletion custom_components/foxess_modbus/entities/modbus_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusSelectDescription(SelectEntityDescription, EntityFactory):
class ModbusSelectDescription(SelectEntityDescription, EntityFactory): # type: ignore[misc]
"""Custom select entity description"""

address: list[ModbusAddressSpec]
Expand Down
2 changes: 1 addition & 1 deletion custom_components/foxess_modbus/entities/modbus_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusSensorDescription(SensorEntityDescription, EntityFactory):
class ModbusSensorDescription(SensorEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Custom sensor description"""

addresses: list[ModbusAddressesSpec]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusVersionSensorDescription(SensorEntityDescription, EntityFactory):
class ModbusVersionSensorDescription(SensorEntityDescription, EntityFactory): # type: ignore[misc, override]
"""Description for ModbusVersionSensor"""

address: list[ModbusAddressSpec]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


@dataclass(kw_only=True, **ENTITY_DESCRIPTION_KWARGS)
class ModbusWorkModeSelectDescription(ModbusSelectDescription):
class ModbusWorkModeSelectDescription(ModbusSelectDescription): # type: ignore[misc, override]
def create_entity_if_supported(
self,
controller: EntityController,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace_packages = true
explicit_package_bases = true

[[tool.mypy.overrides]]
module = 'pymodbus.*'
module = 'serial.*'
ignore_missing_imports = true

[tool.ruff]
Expand Down
8 changes: 4 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# pip>=21.0,<23.2
homeassistant==2025.1.0
homeassistant==2025.1.1

# Testing
pytest-homeassistant-custom-component==0.13.201 # Matching version for 2025.1.0
pytest-homeassistant-custom-component==0.13.202 # Matching version for 2025.1.0
psutil-home-assistant # Not sure why this is needed?
fnv_hash_fast # Or this?
pytest-asyncio
Expand All @@ -13,8 +13,8 @@ black==23.9.0
ruff==0.0.275
# These are duplicated in .pre-commit-config.yaml
reorder-python-imports==3.10.0
mypy==1.14.1
homeassistant-stubs==2025.1.0 # Matching HA version
mypy==1.13.0
homeassistant-stubs==2025.1.1 # Matching HA version
types-python-slugify==8.0.0.2
voluptuous-stubs==0.1.1
# For mypy. Keep in sync with manifest.json and https://github.com/home-assistant/core/blob/master/requirements_all.txt.
Expand Down

0 comments on commit 45d3c0a

Please sign in to comment.