Add daily forecast

This commit is contained in:
Jules 2023-12-24 16:22:58 +01:00
parent 7e15ba34f6
commit 1c50c78f7a
Signed by: jdejaegh
GPG key ID: 99D6D184CA66933A
2 changed files with 53 additions and 9 deletions

View file

@ -2,9 +2,11 @@
from datetime import timedelta, datetime from datetime import timedelta, datetime
import logging import logging
from typing import List
import async_timeout import async_timeout
from homeassistant.components.weather import Forecast
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import (
DataUpdateCoordinator, DataUpdateCoordinator,
@ -17,6 +19,40 @@ from .api import IrmKmiApiClient, IrmKmiApiError
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
def daily_dict_to_forecast(data: List[dict] | None) -> List[Forecast] | None:
if data is None or not isinstance(data, list) or len(data) == 0:
return None
forecasts = list()
n_days = 0
for f in data:
precipitation = None
if f.get('precipQuantity', None) is not None:
precipitation = float(f.get('precipQuantity'))
is_daytime = f.get('dayNight', None) == 'd'
forecast = Forecast(
datetime=(datetime.now() + timedelta(days=n_days)).strftime('%Y-%m-%d')
if is_daytime else datetime.now().strftime('%Y-%m-%d'),
condition=CDT_MAP.get((f.get('ww1'), f.get('dayNight')), None),
native_precipitation=precipitation,
native_temperature=f.get('tempMax', None),
native_templow=f.get('tempMin', None),
native_wind_gust_speed=f.get('wind', {}).get('peakSpeed'),
native_wind_speed=f.get('wind', {}).get('speed'),
precipitation_probability=f.get('precipChance', None),
wind_bearing=f.get('wind', {}).get('dirText', {}).get('en'),
is_daytime=is_daytime,
)
forecasts.append(forecast)
if is_daytime:
n_days += 1
return forecasts
class IrmKmiCoordinator(DataUpdateCoordinator): class IrmKmiCoordinator(DataUpdateCoordinator):
"""Coordinator to update data from IRM KMI""" """Coordinator to update data from IRM KMI"""
@ -43,9 +79,6 @@ class IrmKmiCoordinator(DataUpdateCoordinator):
# Note: asyncio.TimeoutError and aiohttp.ClientError are already # Note: asyncio.TimeoutError and aiohttp.ClientError are already
# handled by the data update coordinator. # handled by the data update coordinator.
async with async_timeout.timeout(10): async with async_timeout.timeout(10):
# Grab active context variables to limit data required to be fetched from API
# Note: using context is not required if there is no need or ability to limit
# data retrieved from API.
api_data = await self._api_client.get_forecasts_coord(self._coord) api_data = await self._api_client.get_forecasts_coord(self._coord)
_LOGGER.debug(f"Observation for {api_data.get('cityName', '')}: {api_data.get('obs', '{}')}") _LOGGER.debug(f"Observation for {api_data.get('cityName', '')}: {api_data.get('obs', '{}')}")
@ -75,14 +108,11 @@ class IrmKmiCoordinator(DataUpdateCoordinator):
'temperature': api_data.get('obs', {}).get('temp'), 'temperature': api_data.get('obs', {}).get('temp'),
'wind_speed': now_hourly.get('windSpeedKm', None) if now_hourly is not None else None, 'wind_speed': now_hourly.get('windSpeedKm', None) if now_hourly is not None else None,
'wind_gust_speed': now_hourly.get('windPeakSpeedKm', None) if now_hourly is not None else None, 'wind_gust_speed': now_hourly.get('windPeakSpeedKm', None) if now_hourly is not None else None,
'wind_bearing': now_hourly.get('windDirection', None) if now_hourly is not None else None, 'wind_bearing': now_hourly.get('windDirectionText', {}).get('en') if now_hourly is not None else None,
'pressure': now_hourly.get('pressure', None) if now_hourly is not None else None, 'pressure': now_hourly.get('pressure', None) if now_hourly is not None else None,
'uv_index': uv_index 'uv_index': uv_index
}, },
'daily_forecast': daily_dict_to_forecast(api_data.get('for', {}).get('daily'))
'hourly_forecast': {
}
} }
return processed_data return processed_data

View file

@ -1,6 +1,7 @@
import logging import logging
from typing import List
from homeassistant.components.weather import WeatherEntity from homeassistant.components.weather import WeatherEntity, WeatherEntityFeature, Forecast
from homeassistant.const import UnitOfTemperature, UnitOfSpeed, UnitOfPrecipitationDepth, UnitOfPressure from homeassistant.const import UnitOfTemperature, UnitOfSpeed, UnitOfPrecipitationDepth, UnitOfPressure
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import (
CoordinatorEntity, CoordinatorEntity,
@ -29,6 +30,12 @@ class IrmKmiWeather(CoordinatorEntity, WeatherEntity):
super().__init__(coordinator) super().__init__(coordinator)
self._name = name self._name = name
@property
def supported_features(self) -> WeatherEntityFeature:
features = WeatherEntityFeature(0)
features |= WeatherEntityFeature.FORECAST_TWICE_DAILY
return features
@property @property
def name(self) -> str: def name(self) -> str:
return self._name return self._name
@ -76,3 +83,10 @@ class IrmKmiWeather(CoordinatorEntity, WeatherEntity):
@property @property
def uv_index(self) -> float | None: def uv_index(self) -> float | None:
return self.coordinator.data.get('current_weather').get('uv_index') return self.coordinator.data.get('current_weather').get('uv_index')
@property
def forecast(self) -> list[Forecast] | None:
return self.coordinator.data.get('daily_forecast')
async def async_forecast_twice_daily(self) -> List[Forecast] | None:
return self.coordinator.data.get('daily_forecast')