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."""
from __future__ import annotations
from datetime import timedelta
from typing import Final
from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT
@ -27,12 +28,14 @@ SENSORS: list[ForecastSolarSensor] = [
ForecastSolarSensor(
key="energy_production_today",
name="Estimated Energy Production - Today",
state=lambda estimate: estimate.energy_production_today / 1000,
device_class=DEVICE_CLASS_ENERGY,
unit_of_measurement=ENERGY_KILO_WATT_HOUR,
),
ForecastSolarSensor(
key="energy_production_tomorrow",
name="Estimated Energy Production - Tomorrow",
state=lambda estimate: estimate.energy_production_tomorrow / 1000,
device_class=DEVICE_CLASS_ENERGY,
unit_of_measurement=ENERGY_KILO_WATT_HOUR,
),
@ -50,11 +53,16 @@ SENSORS: list[ForecastSolarSensor] = [
key="power_production_now",
name="Estimated Power Production - Now",
device_class=DEVICE_CLASS_POWER,
state=lambda estimate: estimate.power_production_now / 1000,
state_class=STATE_CLASS_MEASUREMENT,
unit_of_measurement=POWER_WATT,
),
ForecastSolarSensor(
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",
device_class=DEVICE_CLASS_POWER,
entity_registry_enabled_default=False,
@ -62,6 +70,10 @@ SENSORS: list[ForecastSolarSensor] = [
),
ForecastSolarSensor(
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",
device_class=DEVICE_CLASS_POWER,
entity_registry_enabled_default=False,
@ -69,6 +81,10 @@ SENSORS: list[ForecastSolarSensor] = [
),
ForecastSolarSensor(
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",
device_class=DEVICE_CLASS_POWER,
entity_registry_enabled_default=False,
@ -77,11 +93,13 @@ SENSORS: list[ForecastSolarSensor] = [
ForecastSolarSensor(
key="energy_current_hour",
name="Estimated Energy Production - This Hour",
state=lambda estimate: estimate.energy_current_hour / 1000,
device_class=DEVICE_CLASS_ENERGY,
unit_of_measurement=ENERGY_KILO_WATT_HOUR,
),
ForecastSolarSensor(
key="energy_next_hour",
state=lambda estimate: estimate.sum_energy_production(1) / 1000,
name="Estimated Energy Production - Next Hour",
device_class=DEVICE_CLASS_ENERGY,
unit_of_measurement=ENERGY_KILO_WATT_HOUR,

View File

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

View File

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

View File

@ -66,7 +66,13 @@ class ForecastSolarSensorEntity(CoordinatorEntity, SensorEntity):
@property
def state(self) -> StateType:
"""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):
return state.isoformat()
return state

View File

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

View File

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

View File

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

View File

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