Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
josiasmontag committed Aug 11, 2024
1 parent e2b4031 commit abb5064
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 16 deletions.
3 changes: 2 additions & 1 deletion custom_components/dwd_rain_radar/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class DwdRainRadarConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for the DWD Rain Radar coordinator."""

VERSION = 1
MINOR_VERSION = 1

def __init__(self) -> None:
"""Initialize the config flow."""
Expand Down Expand Up @@ -56,7 +57,7 @@ async def async_step_user(self, user_input=None):
return self.async_show_form(
step_id="user",
data_schema=vol.Schema({
vol.Required(CONF_NAME, default="DWD Rain Radar", description="Name"): str,
vol.Required(CONF_NAME, default="DWD Radar", description="Name"): str,
vol.Optional(CONF_COORDINATES, description="Location"): selector.LocationSelector(
selector.LocationSelectorConfig()
)
Expand Down
2 changes: 2 additions & 0 deletions custom_components/dwd_rain_radar/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

DOMAIN = "dwd_rain_radar"

ATTRIBUTION = "Data provided by Deutscher Wetterdienst (DWD)"

PLATFORMS = [Platform.SENSOR]

CONF_COORDINATES = "coordinates"
Expand Down
6 changes: 5 additions & 1 deletion custom_components/dwd_rain_radar/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import logging
from datetime import datetime, timedelta, timezone
import pandas as pd
from dataclasses import dataclass
from typing import List

Expand Down Expand Up @@ -32,7 +33,7 @@ class PrecipitationForecast:
def from_radolan_data(cls, data) -> PrecipitationForecast:
"""Return instance of Precipitation."""
return cls(
prediction_time=data.prediction_time.values[0],
prediction_time=pd.to_datetime(data.prediction_time.values[0]).to_pydatetime(),
precipitation=data.RV.values.item()
)

Expand All @@ -59,6 +60,7 @@ def __init__(
self.lat = self.coords["latitude"]
self.lon = self.coords["longitude"]
self.radolan = Radolan(self.lat, self.lon, self.async_client)
self.latest_update = None

async def _async_update_data(self) -> List[PrecipitationForecast]:
"""Update the data"""
Expand All @@ -71,4 +73,6 @@ async def _async_update_data(self) -> List[PrecipitationForecast]:

_LOGGER.debug("Fetched forecasts: {}".format(forecasts))

self.latest_update = datetime.now()

return forecasts
46 changes: 37 additions & 9 deletions custom_components/dwd_rain_radar/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,22 @@
SensorStateClass,
)

from .const import DOMAIN
from .const import DOMAIN, ATTRIBUTION
from homeassistant.const import (
ATTR_ATTRIBUTION
)
from .coordinator import DwdRainRadarUpdateCoordinator, PrecipitationForecast
from .entity import DwdCoordinatorEntity


_LOGGER = logging.getLogger(__name__)


@dataclass(frozen=True, kw_only=True)
class PrecipitationSensorEntityDescription(SensorEntityDescription):
"""Provide a description for a precipitation sensor."""

value_fn: Callable[[PrecipitationForecast], float | None]
value_fn: Callable[[PrecipitationForecast]]
extra_state_attributes_fn: Callable[[PrecipitationForecast], dict] = lambda _: {}
exists_fn: Callable[[dict], bool] = lambda _: True


Expand All @@ -41,7 +44,25 @@ class PrecipitationSensorEntityDescription(SensorEntityDescription):
native_unit_of_measurement=UnitOfPrecipitationDepth.MILLIMETERS,
device_class=SensorDeviceClass.PRECIPITATION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda forecast: forecast.precipitation,
value_fn=lambda forecasts: forecasts[0].precipitation,
extra_state_attributes_fn=lambda forecasts: {
'prediction_time': forecasts[0].prediction_time
},
),
PrecipitationSensorEntityDescription(
key="rain_expected_at",
name="Rain Expected At",
device_class=SensorDeviceClass.DATE,
value_fn=lambda forecasts: next(
(forecast.prediction_time for forecast in forecasts if forecast.precipitation > 0),
None
),
extra_state_attributes_fn=lambda forecasts: {
'precipitation': next(
(forecast.precipitation for forecast in forecasts if forecast.precipitation > 0),
None
)
},
)
]

Expand Down Expand Up @@ -72,14 +93,21 @@ def __init__(
super().__init__(coordinator, description)

self._attr_unique_id = (
f"{self.coordinator.config_entry.entry_id}"
+ f"_{self.entity_description.key}"
f"{self.coordinator.config_entry.entry_id}"
+ f"_{self.entity_description.key}"
)

@property
def native_value(self):
"""Return the state of the sensor."""
forecasts = self.coordinator.data
assert forecasts[0] is not None
return self.entity_description.value_fn(self.coordinator.data)

@property
def extra_state_attributes(self):
"""Return the state attributes of the device."""
attributes = self.entity_description.extra_state_attributes_fn(self.coordinator.data)

attributes['latest_update'] = self.coordinator.latest_update
attributes[ATTR_ATTRIBUTION] = ATTRIBUTION

return self.entity_description.value_fn(forecasts[0])
return attributes
16 changes: 11 additions & 5 deletions tests/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,15 @@ async def test_sensor(mock_get, hass, enable_custom_integrations):



state = hass.states.get("sensor.mock_title_precipitation")
precipitation = hass.states.get("sensor.mock_title_precipitation")

assert state
assert state.state == '0.839999973773956'
assert state.attributes['unit_of_measurement'] == 'mm'
assert state.attributes['device_class'] == 'precipitation'
assert precipitation
assert precipitation.state == '0.839999973773956'
assert precipitation.attributes['unit_of_measurement'] == 'mm'
assert precipitation.attributes['device_class'] == 'precipitation'


rain_expected_at = hass.states.get("sensor.mock_title_rain_expected_at")

assert rain_expected_at
assert rain_expected_at.state == '2024-08-08T15:50:00'

0 comments on commit abb5064

Please sign in to comment.