Basic entity class for Imeon inverter integration (#145778)

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: TheBushBoy <theodavid@icloud.com>
This commit is contained in:
Imeon-Energy 2025-06-09 20:04:25 +02:00 committed by GitHub
parent d58157ca9e
commit 7cc8f91bf9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 54 additions and 38 deletions

View File

@ -0,0 +1,40 @@
"""Imeon inverter base class for entities."""
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN
from .coordinator import InverterCoordinator
type InverterConfigEntry = ConfigEntry[InverterCoordinator]
class InverterEntity(CoordinatorEntity[InverterCoordinator]):
"""Common elements for all entities."""
_attr_has_entity_name = True
def __init__(
self,
coordinator: InverterCoordinator,
entry: InverterConfigEntry,
entity_description: EntityDescription,
) -> None:
"""Pass coordinator to CoordinatorEntity."""
super().__init__(coordinator)
self.entity_description = entity_description
self._inverter = coordinator.api.inverter
self.data_key = entity_description.key
assert entry.unique_id
self._attr_unique_id = f"{entry.unique_id}_{self.data_key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, entry.unique_id)},
name="Imeon inverter",
manufacturer="Imeon Energy",
model=self._inverter.get("inverter"),
sw_version=self._inverter.get("software"),
serial_number=self._inverter.get("serial"),
configuration_url=self._inverter.get("url"),
)

View File

@ -21,20 +21,18 @@ from homeassistant.const import (
UnitOfTime,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN
from .coordinator import InverterCoordinator
from .entity import InverterEntity
type InverterConfigEntry = ConfigEntry[InverterCoordinator]
_LOGGER = logging.getLogger(__name__)
ENTITY_DESCRIPTIONS = (
SENSOR_DESCRIPTIONS = (
# Battery
SensorEntityDescription(
key="battery_autonomy",
@ -423,42 +421,18 @@ async def async_setup_entry(
"""Create each sensor for a given config entry."""
coordinator = entry.runtime_data
# Init sensor entities
async_add_entities(
InverterSensor(coordinator, entry, description)
for description in ENTITY_DESCRIPTIONS
for description in SENSOR_DESCRIPTIONS
)
class InverterSensor(CoordinatorEntity[InverterCoordinator], SensorEntity):
"""A sensor that returns numerical values with units."""
class InverterSensor(InverterEntity, SensorEntity):
"""Representation of an Imeon inverter sensor."""
_attr_has_entity_name = True
_attr_entity_category = EntityCategory.DIAGNOSTIC
def __init__(
self,
coordinator: InverterCoordinator,
entry: InverterConfigEntry,
description: SensorEntityDescription,
) -> None:
"""Pass coordinator to CoordinatorEntity."""
super().__init__(coordinator)
self.entity_description = description
self._inverter = coordinator.api.inverter
self.data_key = description.key
assert entry.unique_id
self._attr_unique_id = f"{entry.unique_id}_{self.data_key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, entry.unique_id)},
name="Imeon inverter",
manufacturer="Imeon Energy",
model=self._inverter.get("inverter"),
sw_version=self._inverter.get("software"),
)
@property
def native_value(self) -> StateType | None:
"""Value of the sensor."""
"""Return the state of the entity."""
return self.coordinator.data.get(self.data_key)

View File

@ -60,7 +60,12 @@ def mock_imeon_inverter() -> Generator[MagicMock]:
inverter.__aenter__.return_value = inverter
inverter.login.return_value = True
inverter.get_serial.return_value = TEST_SERIAL
inverter.inverter.get.return_value = {"inverter": "blah", "software": "1.0"}
inverter.inverter = {
"inverter": "3.6",
"software": "1.0",
"serial": TEST_SERIAL,
"url": f"http://{TEST_USER_INPUT[CONF_HOST]}",
}
inverter.storage = load_json_object_fixture("sensor_data.json", DOMAIN)
yield inverter

View File

@ -1,6 +1,6 @@
"""Test the Imeon Inverter sensors."""
from unittest.mock import MagicMock, patch
from unittest.mock import patch
from syrupy.assertion import SnapshotAssertion
@ -15,15 +15,12 @@ from tests.common import MockConfigEntry, snapshot_platform
async def test_sensors(
hass: HomeAssistant,
mock_imeon_inverter: MagicMock,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test the Imeon Inverter sensors."""
with patch(
"homeassistant.components.imeon_inverter.const.PLATFORMS", [Platform.SENSOR]
):
with patch("homeassistant.components.imeon_inverter.PLATFORMS", [Platform.SENSOR]):
await setup_integration(hass, mock_config_entry)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)