Migrate forecast solar to v2 (#53259)

This commit is contained in:
Paulus Schoutsen 2021-07-21 15:04:30 -07:00 committed by GitHub
parent 9f14b2cef5
commit edf42bab25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 64 additions and 27 deletions

View File

@ -1,6 +1,7 @@
"""Constants for the Forecast.Solar integration.""" """Constants for the Forecast.Solar integration."""
from __future__ import annotations from __future__ import annotations
from datetime import timedelta
from typing import Final from typing import Final
from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT
@ -27,12 +28,14 @@ SENSORS: list[ForecastSolarSensor] = [
ForecastSolarSensor( ForecastSolarSensor(
key="energy_production_today", key="energy_production_today",
name="Estimated Energy Production - Today", name="Estimated Energy Production - Today",
state=lambda estimate: estimate.energy_production_today / 1000,
device_class=DEVICE_CLASS_ENERGY, device_class=DEVICE_CLASS_ENERGY,
unit_of_measurement=ENERGY_KILO_WATT_HOUR, unit_of_measurement=ENERGY_KILO_WATT_HOUR,
), ),
ForecastSolarSensor( ForecastSolarSensor(
key="energy_production_tomorrow", key="energy_production_tomorrow",
name="Estimated Energy Production - Tomorrow", name="Estimated Energy Production - Tomorrow",
state=lambda estimate: estimate.energy_production_tomorrow / 1000,
device_class=DEVICE_CLASS_ENERGY, device_class=DEVICE_CLASS_ENERGY,
unit_of_measurement=ENERGY_KILO_WATT_HOUR, unit_of_measurement=ENERGY_KILO_WATT_HOUR,
), ),
@ -50,11 +53,16 @@ SENSORS: list[ForecastSolarSensor] = [
key="power_production_now", key="power_production_now",
name="Estimated Power Production - Now", name="Estimated Power Production - Now",
device_class=DEVICE_CLASS_POWER, device_class=DEVICE_CLASS_POWER,
state=lambda estimate: estimate.power_production_now / 1000,
state_class=STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=POWER_WATT, unit_of_measurement=POWER_WATT,
), ),
ForecastSolarSensor( ForecastSolarSensor(
key="power_production_next_hour", key="power_production_next_hour",
state=lambda estimate: estimate.power_production_at_time(
estimate.now() + timedelta(hours=1)
)
/ 1000,
name="Estimated Power Production - Next Hour", name="Estimated Power Production - Next Hour",
device_class=DEVICE_CLASS_POWER, device_class=DEVICE_CLASS_POWER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
@ -62,6 +70,10 @@ SENSORS: list[ForecastSolarSensor] = [
), ),
ForecastSolarSensor( ForecastSolarSensor(
key="power_production_next_12hours", key="power_production_next_12hours",
state=lambda estimate: estimate.power_production_at_time(
estimate.now() + timedelta(hours=12)
)
/ 1000,
name="Estimated Power Production - Next 12 Hours", name="Estimated Power Production - Next 12 Hours",
device_class=DEVICE_CLASS_POWER, device_class=DEVICE_CLASS_POWER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
@ -69,6 +81,10 @@ SENSORS: list[ForecastSolarSensor] = [
), ),
ForecastSolarSensor( ForecastSolarSensor(
key="power_production_next_24hours", key="power_production_next_24hours",
state=lambda estimate: estimate.power_production_at_time(
estimate.now() + timedelta(hours=24)
)
/ 1000,
name="Estimated Power Production - Next 24 Hours", name="Estimated Power Production - Next 24 Hours",
device_class=DEVICE_CLASS_POWER, device_class=DEVICE_CLASS_POWER,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
@ -77,11 +93,13 @@ SENSORS: list[ForecastSolarSensor] = [
ForecastSolarSensor( ForecastSolarSensor(
key="energy_current_hour", key="energy_current_hour",
name="Estimated Energy Production - This Hour", name="Estimated Energy Production - This Hour",
state=lambda estimate: estimate.energy_current_hour / 1000,
device_class=DEVICE_CLASS_ENERGY, device_class=DEVICE_CLASS_ENERGY,
unit_of_measurement=ENERGY_KILO_WATT_HOUR, unit_of_measurement=ENERGY_KILO_WATT_HOUR,
), ),
ForecastSolarSensor( ForecastSolarSensor(
key="energy_next_hour", key="energy_next_hour",
state=lambda estimate: estimate.sum_energy_production(1) / 1000,
name="Estimated Energy Production - Next Hour", name="Estimated Energy Production - Next Hour",
device_class=DEVICE_CLASS_ENERGY, device_class=DEVICE_CLASS_ENERGY,
unit_of_measurement=ENERGY_KILO_WATT_HOUR, unit_of_measurement=ENERGY_KILO_WATT_HOUR,

View File

@ -3,7 +3,7 @@
"name": "Forecast.Solar", "name": "Forecast.Solar",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/forecast_solar", "documentation": "https://www.home-assistant.io/integrations/forecast_solar",
"requirements": ["forecast_solar==1.3.1"], "requirements": ["forecast_solar==2.0.0"],
"codeowners": ["@klaasnicolaas", "@frenck"], "codeowners": ["@klaasnicolaas", "@frenck"],
"quality_scale": "platinum", "quality_scale": "platinum",
"iot_class": "cloud_polling" "iot_class": "cloud_polling"

View File

@ -2,6 +2,9 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, Callable
from forecast_solar.models import Estimate
@dataclass @dataclass
@ -13,5 +16,6 @@ class ForecastSolarSensor:
device_class: str | None = None device_class: str | None = None
entity_registry_enabled_default: bool = True entity_registry_enabled_default: bool = True
state: Callable[[Estimate], Any] | None = None
state_class: str | None = None state_class: str | None = None
unit_of_measurement: str | None = None unit_of_measurement: str | None = None

View File

@ -66,7 +66,13 @@ class ForecastSolarSensorEntity(CoordinatorEntity, SensorEntity):
@property @property
def state(self) -> StateType: def state(self) -> StateType:
"""Return the state of the sensor.""" """Return the state of the sensor."""
state: StateType | datetime = getattr(self.coordinator.data, self._sensor.key) if self._sensor.state is None:
state: StateType | datetime = getattr(
self.coordinator.data, self._sensor.key
)
else:
state = self._sensor.state(self.coordinator.data)
if isinstance(state, datetime): if isinstance(state, datetime):
return state.isoformat() return state.isoformat()
return state return state

View File

@ -630,7 +630,7 @@ fnvhash==0.1.0
foobot_async==1.0.0 foobot_async==1.0.0
# homeassistant.components.forecast_solar # homeassistant.components.forecast_solar
forecast_solar==1.3.1 forecast_solar==2.0.0
# homeassistant.components.fortios # homeassistant.components.fortios
fortiosapi==1.0.5 fortiosapi==1.0.5

View File

@ -348,7 +348,7 @@ fnvhash==0.1.0
foobot_async==1.0.0 foobot_async==1.0.0
# homeassistant.components.forecast_solar # homeassistant.components.forecast_solar
forecast_solar==1.3.1 forecast_solar==2.0.0
# homeassistant.components.freebox # homeassistant.components.freebox
freebox-api==0.0.10 freebox-api==0.0.10

View File

@ -1,9 +1,10 @@
"""Fixtures for Forecast.Solar integration tests.""" """Fixtures for Forecast.Solar integration tests."""
import datetime from datetime import datetime, timedelta
from typing import Generator from typing import Generator
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from forecast_solar import models
import pytest import pytest
from homeassistant.components.forecast_solar.const import ( from homeassistant.components.forecast_solar.const import (
@ -16,6 +17,7 @@ from homeassistant.components.forecast_solar.const import (
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
@ -54,24 +56,31 @@ def mock_forecast_solar() -> Generator[None, MagicMock, None]:
"homeassistant.components.forecast_solar.ForecastSolar", autospec=True "homeassistant.components.forecast_solar.ForecastSolar", autospec=True
) as forecast_solar_mock: ) as forecast_solar_mock:
forecast_solar = forecast_solar_mock.return_value forecast_solar = forecast_solar_mock.return_value
now = datetime(2021, 6, 27, 6, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE)
estimate = MagicMock() estimate = MagicMock(spec_set=models.Estimate)
estimate.now.return_value = now
estimate.timezone = "Europe/Amsterdam" estimate.timezone = "Europe/Amsterdam"
estimate.energy_production_today = 100 estimate.energy_production_today = 100000
estimate.energy_production_tomorrow = 200 estimate.energy_production_tomorrow = 200000
estimate.power_production_now = 300 estimate.power_production_now = 300000
estimate.power_highest_peak_time_today = datetime.datetime( estimate.power_highest_peak_time_today = datetime(
2021, 6, 27, 13, 0, tzinfo=datetime.timezone.utc 2021, 6, 27, 13, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE
) )
estimate.power_highest_peak_time_tomorrow = datetime.datetime( estimate.power_highest_peak_time_tomorrow = datetime(
2021, 6, 27, 14, 0, tzinfo=datetime.timezone.utc 2021, 6, 27, 14, 0, tzinfo=dt_util.DEFAULT_TIME_ZONE
) )
estimate.power_production_next_hour = 400 estimate.energy_current_hour = 800000
estimate.power_production_next_6hours = 500
estimate.power_production_next_12hours = 600 estimate.power_production_at_time.side_effect = {
estimate.power_production_next_24hours = 700 now + timedelta(hours=1): 400000,
estimate.energy_current_hour = 800 now + timedelta(hours=12): 600000,
estimate.energy_next_hour = 900 now + timedelta(hours=24): 700000,
}.get
estimate.sum_energy_production.side_effect = {
1: 900000,
}.get
forecast_solar.estimate.return_value = estimate forecast_solar.estimate.return_value = estimate
yield forecast_solar yield forecast_solar

View File

@ -40,7 +40,7 @@ async def test_sensors(
assert entry assert entry
assert state assert state
assert entry.unique_id == f"{entry_id}_energy_production_today" assert entry.unique_id == f"{entry_id}_energy_production_today"
assert state.state == "100" assert state.state == "100.0"
assert ( assert (
state.attributes.get(ATTR_FRIENDLY_NAME) state.attributes.get(ATTR_FRIENDLY_NAME)
== "Estimated Energy Production - Today" == "Estimated Energy Production - Today"
@ -55,7 +55,7 @@ async def test_sensors(
assert entry assert entry
assert state assert state
assert entry.unique_id == f"{entry_id}_energy_production_tomorrow" assert entry.unique_id == f"{entry_id}_energy_production_tomorrow"
assert state.state == "200" assert state.state == "200.0"
assert ( assert (
state.attributes.get(ATTR_FRIENDLY_NAME) state.attributes.get(ATTR_FRIENDLY_NAME)
== "Estimated Energy Production - Tomorrow" == "Estimated Energy Production - Tomorrow"
@ -96,7 +96,7 @@ async def test_sensors(
assert entry assert entry
assert state assert state
assert entry.unique_id == f"{entry_id}_power_production_now" assert entry.unique_id == f"{entry_id}_power_production_now"
assert state.state == "300" assert state.state == "300.0"
assert ( assert (
state.attributes.get(ATTR_FRIENDLY_NAME) == "Estimated Power Production - Now" state.attributes.get(ATTR_FRIENDLY_NAME) == "Estimated Power Production - Now"
) )
@ -110,7 +110,7 @@ async def test_sensors(
assert entry assert entry
assert state assert state
assert entry.unique_id == f"{entry_id}_energy_current_hour" assert entry.unique_id == f"{entry_id}_energy_current_hour"
assert state.state == "800" assert state.state == "800.0"
assert ( assert (
state.attributes.get(ATTR_FRIENDLY_NAME) state.attributes.get(ATTR_FRIENDLY_NAME)
== "Estimated Energy Production - This Hour" == "Estimated Energy Production - This Hour"
@ -125,7 +125,7 @@ async def test_sensors(
assert entry assert entry
assert state assert state
assert entry.unique_id == f"{entry_id}_energy_next_hour" assert entry.unique_id == f"{entry_id}_energy_next_hour"
assert state.state == "900" assert state.state == "900.0"
assert ( assert (
state.attributes.get(ATTR_FRIENDLY_NAME) state.attributes.get(ATTR_FRIENDLY_NAME)
== "Estimated Energy Production - Next Hour" == "Estimated Energy Production - Next Hour"
@ -175,17 +175,17 @@ async def test_disabled_by_default(
( (
"power_production_next_12hours", "power_production_next_12hours",
"Estimated Power Production - Next 12 Hours", "Estimated Power Production - Next 12 Hours",
"600", "600.0",
), ),
( (
"power_production_next_24hours", "power_production_next_24hours",
"Estimated Power Production - Next 24 Hours", "Estimated Power Production - Next 24 Hours",
"700", "700.0",
), ),
( (
"power_production_next_hour", "power_production_next_hour",
"Estimated Power Production - Next Hour", "Estimated Power Production - Next Hour",
"400", "400.0",
), ),
], ],
) )