Bump solarlog_cli to 0.2.2 (#124948)

* Add inverter-devices

* Minor code adjustments

* Update manifest.json

Seperate dependency upgrade to seperate PR

* Update requirements_all.txt

Seperate dependency upgrade to seperate PR

* Update requirements_test_all.txt

Seperate dependency upgrade to seperate PR

* Update homeassistant/components/solarlog/sensor.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Split up base class, document SolarLogSensorEntityDescription

* Split up sensor types

* Update snapshot

* Bump solarlog_cli to 0.2.1

* Add strict typing

* Bump fyta_cli to 0.6.3 (#124574)

* Ensure write access to hassrelease data folder (#124573)

Co-authored-by: Robert Resch <robert@resch.dev>

* Update a roborock blocking call to be fully async (#124266)

Remove a blocking call in roborock

* Add inverter-devices

* Split up sensor types

* Update snapshot

* Bump solarlog_cli to 0.2.1

* Backport/rebase

* Tidy up

* Simplyfication coordinator.py

* Minor adjustments

* Ruff

* Bump solarlog_cli to 0.2.2

* Update homeassistant/components/solarlog/sensor.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Update homeassistant/components/solarlog/config_flow.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Update homeassistant/components/solarlog/sensor.py

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Update persentage-values in fixture

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: Robert Resch <robert@resch.dev>
Co-authored-by: Allen Porter <allen@thebends.org>
pull/124597/head
dontinelli 2024-09-01 12:47:52 +02:00 committed by GitHub
parent 68162e1a27
commit 1661304f10
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 350 additions and 125 deletions

View File

@ -411,6 +411,7 @@ homeassistant.components.slack.*
homeassistant.components.sleepiq.*
homeassistant.components.smhi.*
homeassistant.components.snooz.*
homeassistant.components.solarlog.*
homeassistant.components.sonarr.*
homeassistant.components.speedtestdotnet.*
homeassistant.components.sql.*

View File

@ -19,7 +19,7 @@ _LOGGER = logging.getLogger(__name__)
@callback
def solarlog_entries(hass: HomeAssistant):
def solarlog_entries(hass: HomeAssistant) -> set[str]:
"""Return the hosts already configured."""
return {
entry.data[CONF_HOST] for entry in hass.config_entries.async_entries(DOMAIN)
@ -36,7 +36,7 @@ class SolarLogConfigFlow(ConfigFlow, domain=DOMAIN):
"""Initialize the config flow."""
self._errors: dict = {}
def _host_in_configuration_exists(self, host) -> bool:
def _host_in_configuration_exists(self, host: str) -> bool:
"""Return True if host exists in configuration."""
if host in solarlog_entries(self.hass):
return True
@ -50,7 +50,7 @@ class SolarLogConfigFlow(ConfigFlow, domain=DOMAIN):
url = ParseResult("http", netloc, path, *url[3:])
return url.geturl()
async def _test_connection(self, host):
async def _test_connection(self, host: str) -> bool:
"""Check if we can connect to the Solar-Log device."""
solarlog = SolarLogConnector(host)
try:
@ -66,11 +66,12 @@ class SolarLogConfigFlow(ConfigFlow, domain=DOMAIN):
return True
async def async_step_user(self, user_input=None) -> ConfigFlowResult:
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Step when user initializes a integration."""
self._errors = {}
if user_input is not None:
# set some defaults in case we need to return to the form
user_input[CONF_NAME] = slugify(user_input[CONF_NAME])
user_input[CONF_HOST] = self._parse_url(user_input[CONF_HOST])
@ -81,20 +82,14 @@ class SolarLogConfigFlow(ConfigFlow, domain=DOMAIN):
title=user_input[CONF_NAME], data=user_input
)
else:
user_input = {}
user_input[CONF_NAME] = DEFAULT_NAME
user_input[CONF_HOST] = DEFAULT_HOST
user_input = {CONF_NAME: DEFAULT_NAME, CONF_HOST: DEFAULT_HOST}
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(
CONF_NAME, default=user_input.get(CONF_NAME, DEFAULT_NAME)
): str,
vol.Required(
CONF_HOST, default=user_input.get(CONF_HOST, DEFAULT_HOST)
): str,
vol.Required(CONF_NAME, default=user_input[CONF_NAME]): str,
vol.Required(CONF_HOST, default=user_input[CONF_HOST]): str,
vol.Required("extended_data", default=False): bool,
}
),

View File

@ -12,11 +12,12 @@ from solarlog_cli.solarlog_exceptions import (
SolarLogConnectionError,
SolarLogUpdateError,
)
from solarlog_cli.solarlog_models import SolarlogData
from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import update_coordinator
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
_LOGGER = logging.getLogger(__name__)
@ -24,7 +25,7 @@ if TYPE_CHECKING:
from . import SolarlogConfigEntry
class SolarLogCoordinator(update_coordinator.DataUpdateCoordinator):
class SolarLogCoordinator(DataUpdateCoordinator[SolarlogData]):
"""Get and update the latest data."""
def __init__(self, hass: HomeAssistant, entry: SolarlogConfigEntry) -> None:
@ -43,29 +44,29 @@ class SolarLogCoordinator(update_coordinator.DataUpdateCoordinator):
self.name = entry.title
self.host = url.geturl()
extended_data = entry.data["extended_data"]
self.solarlog = SolarLogConnector(
self.host, extended_data, hass.config.time_zone
self.host, entry.data["extended_data"], hass.config.time_zone
)
async def _async_setup(self) -> None:
"""Do initialization logic."""
if self.solarlog.extended_data:
device_list = await self.solarlog.client.get_device_list()
device_list = await self.solarlog.update_device_list()
self.solarlog.set_enabled_devices({key: True for key in device_list})
async def _async_update_data(self):
async def _async_update_data(self) -> SolarlogData:
"""Update the data from the SolarLog device."""
_LOGGER.debug("Start data update")
try:
data = await self.solarlog.update_data()
await self.solarlog.update_device_list()
if self.solarlog.extended_data:
await self.solarlog.update_device_list()
data.inverter_data = await self.solarlog.update_inverter_data()
except SolarLogConnectionError as err:
raise ConfigEntryNotReady(err) from err
except SolarLogUpdateError as err:
raise update_coordinator.UpdateFailed(err) from err
raise UpdateFailed(err) from err
_LOGGER.debug("Data successfully updated")

View File

@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/solarlog",
"iot_class": "local_polling",
"loggers": ["solarlog_cli"],
"requirements": ["solarlog_cli==0.1.6"]
"requirements": ["solarlog_cli==0.2.2"]
}

View File

@ -5,7 +5,8 @@ from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from datetime import datetime
from typing import Any
from solarlog_cli.solarlog_models import InverterData, SolarlogData
from homeassistant.components.sensor import (
SensorDeviceClass,
@ -21,200 +22,219 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from . import SolarlogConfigEntry
from .entity import SolarLogCoordinatorEntity, SolarLogInverterEntity
@dataclass(frozen=True)
class SolarLogSensorEntityDescription(SensorEntityDescription):
"""Describes Solarlog sensor entity."""
@dataclass(frozen=True, kw_only=True)
class SolarLogCoordinatorSensorEntityDescription(SensorEntityDescription):
"""Describes Solarlog coordinator sensor entity."""
value_fn: Callable[[float | int], float] | Callable[[datetime], datetime] = (
lambda value: value
)
value_fn: Callable[[SolarlogData], StateType | datetime | None]
SOLARLOG_SENSOR_TYPES: tuple[SolarLogSensorEntityDescription, ...] = (
SolarLogSensorEntityDescription(
@dataclass(frozen=True, kw_only=True)
class SolarLogInverterSensorEntityDescription(SensorEntityDescription):
"""Describes Solarlog inverter sensor entity."""
value_fn: Callable[[InverterData], float | None]
SOLARLOG_SENSOR_TYPES: tuple[SolarLogCoordinatorSensorEntityDescription, ...] = (
SolarLogCoordinatorSensorEntityDescription(
key="last_updated",
translation_key="last_update",
device_class=SensorDeviceClass.TIMESTAMP,
value_fn=lambda data: data.last_updated,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="power_ac",
translation_key="power_ac",
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.power_ac,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="power_dc",
translation_key="power_dc",
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.power_dc,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="voltage_ac",
translation_key="voltage_ac",
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.voltage_ac,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="voltage_dc",
translation_key="voltage_dc",
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.voltage_dc,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="yield_day",
translation_key="yield_day",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.yield_day / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="yield_yesterday",
translation_key="yield_yesterday",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.yield_yesterday / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="yield_month",
translation_key="yield_month",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.yield_month / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="yield_year",
translation_key="yield_year",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.yield_year / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="yield_total",
translation_key="yield_total",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.yield_total / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="consumption_ac",
translation_key="consumption_ac",
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.consumption_ac,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="consumption_day",
translation_key="consumption_day",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.consumption_day / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="consumption_yesterday",
translation_key="consumption_yesterday",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.consumption_yesterday / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="consumption_month",
translation_key="consumption_month",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.consumption_month / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="consumption_year",
translation_key="consumption_year",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.consumption_year / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="consumption_total",
translation_key="consumption_total",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda data: round(data.consumption_total / 1000, 3),
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="self_consumption_year",
translation_key="self_consumption_year",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
value_fn=lambda data: data.self_consumption_year,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="total_power",
translation_key="total_power",
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
value_fn=lambda data: data.total_power,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="alternator_loss",
translation_key="alternator_loss",
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.alternator_loss,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="capacity",
translation_key="capacity",
native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda value: round(value * 100, 1),
value_fn=lambda data: data.capacity,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="efficiency",
translation_key="efficiency",
native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda value: round(value * 100, 1),
value_fn=lambda data: data.efficiency,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="power_available",
translation_key="power_available",
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.power_available,
),
SolarLogSensorEntityDescription(
SolarLogCoordinatorSensorEntityDescription(
key="usage",
translation_key="usage",
native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda value: round(value * 100, 1),
value_fn=lambda data: data.usage,
),
)
INVERTER_SENSOR_TYPES: tuple[SolarLogSensorEntityDescription, ...] = (
SolarLogSensorEntityDescription(
INVERTER_SENSOR_TYPES: tuple[SolarLogInverterSensorEntityDescription, ...] = (
SolarLogInverterSensorEntityDescription(
key="current_power",
translation_key="current_power",
native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda inverter: inverter.current_power,
),
SolarLogSensorEntityDescription(
SolarLogInverterSensorEntityDescription(
key="consumption_year",
translation_key="consumption_year",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY,
value_fn=lambda value: round(value / 1000, 3),
value_fn=lambda inverter: None
if inverter.consumption_year is None
else round(inverter.consumption_year / 1000, 3),
),
)
@ -227,21 +247,18 @@ async def async_setup_entry(
"""Add solarlog entry."""
coordinator = entry.runtime_data
# https://github.com/python/mypy/issues/14294
entities: list[SensorEntity] = [
SolarLogCoordinatorSensor(coordinator, sensor)
for sensor in SOLARLOG_SENSOR_TYPES
]
device_data: dict[str, Any] = coordinator.data["devices"]
device_data = coordinator.data.inverter_data
if not device_data:
if device_data:
entities.extend(
SolarLogInverterSensor(coordinator, sensor, int(device_id))
SolarLogInverterSensor(coordinator, sensor, device_id)
for device_id in device_data
for sensor in INVERTER_SENSOR_TYPES
if sensor.key in device_data[device_id]
)
async_add_entities(entities)
@ -250,26 +267,24 @@ async def async_setup_entry(
class SolarLogCoordinatorSensor(SolarLogCoordinatorEntity, SensorEntity):
"""Represents a SolarLog sensor."""
entity_description: SolarLogSensorEntityDescription
entity_description: SolarLogCoordinatorSensorEntityDescription
@property
def native_value(self) -> float | datetime:
def native_value(self) -> StateType | datetime:
"""Return the state for this sensor."""
val = self.coordinator.data[self.entity_description.key]
return self.entity_description.value_fn(val)
return self.entity_description.value_fn(self.coordinator.data)
class SolarLogInverterSensor(SolarLogInverterEntity, SensorEntity):
"""Represents a SolarLog inverter sensor."""
entity_description: SolarLogSensorEntityDescription
entity_description: SolarLogInverterSensorEntityDescription
@property
def native_value(self) -> float | datetime:
def native_value(self) -> StateType:
"""Return the state for this sensor."""
val = self.coordinator.data["devices"][self.device_id][
self.entity_description.key
]
return self.entity_description.value_fn(val)
return self.entity_description.value_fn(
self.coordinator.data.inverter_data[self.device_id]
)

View File

@ -3866,6 +3866,16 @@ disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.solarlog.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_decorators = true
disallow_untyped_defs = true
warn_return_any = true
warn_unreachable = true
[mypy-homeassistant.components.sonarr.*]
check_untyped_defs = true
disallow_incomplete_defs = true

View File

@ -2650,7 +2650,7 @@ soco==0.30.4
solaredge-local==0.2.3
# homeassistant.components.solarlog
solarlog_cli==0.1.6
solarlog_cli==0.2.2
# homeassistant.components.solax
solax==3.1.1

View File

@ -2093,7 +2093,7 @@ snapcast==2.3.6
soco==0.30.4
# homeassistant.components.solarlog
solarlog_cli==0.1.6
solarlog_cli==0.2.2
# homeassistant.components.solax
solax==3.1.1

View File

@ -17,3 +17,5 @@ async def setup_platform(
with patch("homeassistant.components.solarlog.PLATFORMS", platforms):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
return config_entry

View File

@ -1,10 +1,10 @@
"""Test helpers."""
from collections.abc import Generator
from datetime import UTC, datetime
from unittest.mock import AsyncMock, patch
import pytest
from solarlog_cli.solarlog_models import InverterData, SolarlogData
from homeassistant.components.solarlog.const import DOMAIN as SOLARLOG_DOMAIN
from homeassistant.const import CONF_HOST, CONF_NAME
@ -13,6 +13,19 @@ from .const import HOST, NAME
from tests.common import MockConfigEntry, load_json_object_fixture
DEVICE_LIST = {
0: InverterData(name="Inverter 1", enabled=True),
1: InverterData(name="Inverter 2", enabled=True),
}
INVERTER_DATA = {
0: InverterData(
name="Inverter 1", enabled=True, consumption_year=354687, current_power=5
),
1: InverterData(
name="Inverter 2", enabled=True, consumption_year=354, current_power=6
),
}
@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
@ -34,28 +47,18 @@ def mock_config_entry() -> MockConfigEntry:
def mock_solarlog_connector():
"""Build a fixture for the SolarLog API that connects successfully and returns one device."""
data = SolarlogData.from_dict(
load_json_object_fixture("solarlog_data.json", SOLARLOG_DOMAIN)
)
data.inverter_data = INVERTER_DATA
mock_solarlog_api = AsyncMock()
mock_solarlog_api.test_connection = AsyncMock(return_value=True)
data = {
"devices": {
0: {"consumption_total": 354687, "current_power": 5},
}
}
data |= load_json_object_fixture("solarlog_data.json", SOLARLOG_DOMAIN)
data["last_updated"] = datetime.fromisoformat(data["last_updated"]).astimezone(UTC)
mock_solarlog_api.test_connection.return_value = True
mock_solarlog_api.update_data.return_value = data
mock_solarlog_api.device_list.return_value = {
0: {"name": "Inverter 1"},
1: {"name": "Inverter 2"},
}
mock_solarlog_api.update_device_list.return_value = INVERTER_DATA
mock_solarlog_api.update_inverter_data.return_value = INVERTER_DATA
mock_solarlog_api.device_name = {0: "Inverter 1", 1: "Inverter 2"}.get
mock_solarlog_api.client.get_device_list.return_value = {
0: {"name": "Inverter 1"},
1: {"name": "Inverter 2"},
}
mock_solarlog_api.client.close = AsyncMock(return_value=None)
mock_solarlog_api.device_enabled = {0: True, 1: False}.get
with (
patch(

View File

@ -17,9 +17,9 @@
"total_power": 120,
"self_consumption_year": 545,
"alternator_loss": 2,
"efficiency": 0.9804,
"usage": 0.5487,
"efficiency": 98.1,
"usage": 54.8,
"power_available": 45.13,
"capacity": 0.85,
"last_updated": "2024-08-01T15:20:45"
"capacity": 85.5,
"last_updated": "2024-08-01T15:20:45Z"
}

View File

@ -1,4 +1,103 @@
# serializer version: 1
# name: test_all_entities[sensor.inverter_1_consumption_total-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.TOTAL: 'total'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.inverter_1_consumption_total',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Consumption total',
'platform': 'solarlog',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'consumption_total',
'unique_id': 'ce5f5431554d101905d31797e1232da8-inverter_1-consumption_total',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_all_entities[sensor.inverter_1_consumption_total-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Inverter 1 Consumption total',
'state_class': <SensorStateClass.TOTAL: 'total'>,
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.inverter_1_consumption_total',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '354.687',
})
# ---
# name: test_all_entities[sensor.inverter_1_consumption_year-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.inverter_1_consumption_year',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Consumption year',
'platform': 'solarlog',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'consumption_year',
'unique_id': 'ce5f5431554d101905d31797e1232da8-inverter_1-consumption_year',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_all_entities[sensor.inverter_1_consumption_year-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Inverter 1 Consumption year',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.inverter_1_consumption_year',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '354.687',
})
# ---
# name: test_all_entities[sensor.inverter_1_power-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@ -50,6 +149,105 @@
'state': '5',
})
# ---
# name: test_all_entities[sensor.inverter_2_consumption_year-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.inverter_2_consumption_year',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Consumption year',
'platform': 'solarlog',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'consumption_year',
'unique_id': 'ce5f5431554d101905d31797e1232da8-inverter_2-consumption_year',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
})
# ---
# name: test_all_entities[sensor.inverter_2_consumption_year-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Inverter 2 Consumption year',
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
}),
'context': <ANY>,
'entity_id': 'sensor.inverter_2_consumption_year',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0.354',
})
# ---
# name: test_all_entities[sensor.inverter_2_power-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.inverter_2_power',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
'original_icon': None,
'original_name': 'Power',
'platform': 'solarlog',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'current_power',
'unique_id': 'ce5f5431554d101905d31797e1232da8-inverter_2-current_power',
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
})
# ---
# name: test_all_entities[sensor.inverter_2_power-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'power',
'friendly_name': 'Inverter 2 Power',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
}),
'context': <ANY>,
'entity_id': 'sensor.inverter_2_power',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '6',
})
# ---
# name: test_all_entities[sensor.solarlog_alternator_loss-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@ -98,7 +296,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2',
'state': '2.0',
})
# ---
# name: test_all_entities[sensor.solarlog_capacity-entry]
@ -149,7 +347,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '85.0',
'state': '85.5',
})
# ---
# name: test_all_entities[sensor.solarlog_consumption_ac-entry]
@ -494,7 +692,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '98.0',
'state': '98.1',
})
# ---
# name: test_all_entities[sensor.solarlog_installed_peak_power-entry]
@ -542,7 +740,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '120',
'state': '120.0',
})
# ---
# name: test_all_entities[sensor.solarlog_last_update-entry]
@ -640,7 +838,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '100',
'state': '100.0',
})
# ---
# name: test_all_entities[sensor.solarlog_power_available-entry]
@ -742,7 +940,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '102',
'state': '102.0',
})
# ---
# name: test_all_entities[sensor.solarlog_self_consumption_year-entry]
@ -793,7 +991,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '545',
'state': '545.0',
})
# ---
# name: test_all_entities[sensor.solarlog_usage-entry]
@ -844,7 +1042,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '54.9',
'state': '54.8',
})
# ---
# name: test_all_entities[sensor.solarlog_voltage_ac-entry]
@ -895,7 +1093,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '100',
'state': '100.0',
})
# ---
# name: test_all_entities[sensor.solarlog_voltage_dc-entry]
@ -946,7 +1144,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '100',
'state': '100.0',
})
# ---
# name: test_all_entities[sensor.solarlog_yield_day-entry]

View File

@ -123,7 +123,7 @@ async def test_form_exceptions(
assert result["data"]["extended_data"] is False
async def test_abort_if_already_setup(hass: HomeAssistant, test_connect) -> None:
async def test_abort_if_already_setup(hass: HomeAssistant, test_connect: None) -> None:
"""Test we abort if the device is already setup."""
flow = init_config_flow(hass)
MockConfigEntry(