mirror of
https://github.com/jdejaegh/irm-kmi-ha.git
synced 2025-06-27 03:35:56 +02:00
Fetch sunrise and sunset time for daily forecast
This commit is contained in:
parent
48ad275cf9
commit
0059b2f78f
3 changed files with 75 additions and 7 deletions
|
@ -19,16 +19,18 @@ from homeassistant.util import dt
|
||||||
from homeassistant.util.dt import utcnow
|
from homeassistant.util.dt import utcnow
|
||||||
|
|
||||||
from .api import IrmKmiApiClient, IrmKmiApiError
|
from .api import IrmKmiApiClient, IrmKmiApiError
|
||||||
from .const import CONF_DARK_MODE, CONF_STYLE, DOMAIN, IRM_KMI_NAME, WEEKDAYS
|
from .const import CONF_DARK_MODE, CONF_STYLE, DOMAIN, IRM_KMI_NAME
|
||||||
from .const import IRM_KMI_TO_HA_CONDITION_MAP as CDT_MAP
|
from .const import IRM_KMI_TO_HA_CONDITION_MAP as CDT_MAP
|
||||||
from .const import MAP_WARNING_ID_TO_SLUG as SLUG_MAP
|
from .const import MAP_WARNING_ID_TO_SLUG as SLUG_MAP
|
||||||
from .const import OPTION_STYLE_SATELLITE, OUT_OF_BENELUX, STYLE_TO_PARAM_MAP
|
from .const import (OPTION_STYLE_SATELLITE, OUT_OF_BENELUX, STYLE_TO_PARAM_MAP,
|
||||||
|
WEEKDAYS)
|
||||||
from .data import (AnimationFrameData, CurrentWeatherData, IrmKmiForecast,
|
from .data import (AnimationFrameData, CurrentWeatherData, IrmKmiForecast,
|
||||||
IrmKmiRadarForecast, ProcessedCoordinatorData,
|
IrmKmiRadarForecast, ProcessedCoordinatorData,
|
||||||
RadarAnimationData, WarningData)
|
RadarAnimationData, WarningData)
|
||||||
from .pollen import PollenParser
|
from .pollen import PollenParser
|
||||||
from .rain_graph import RainGraph
|
from .rain_graph import RainGraph
|
||||||
from .utils import disable_from_config, get_config_value, preferred_language, next_weekday
|
from .utils import (disable_from_config, get_config_value, next_weekday,
|
||||||
|
preferred_language)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -351,14 +353,14 @@ class IrmKmiCoordinator(TimestampDataUpdateCoordinator):
|
||||||
IrmKmiRadarForecast(
|
IrmKmiRadarForecast(
|
||||||
datetime=f.get("time"),
|
datetime=f.get("time"),
|
||||||
native_precipitation=f.get('value'),
|
native_precipitation=f.get('value'),
|
||||||
rain_forecast_max=round(f.get('positionHigher')*ratio, 2),
|
rain_forecast_max=round(f.get('positionHigher') * ratio, 2),
|
||||||
rain_forecast_min=round(f.get('positionLower')*ratio, 2),
|
rain_forecast_min=round(f.get('positionLower') * ratio, 2),
|
||||||
might_rain=f.get('positionHigher') > 0
|
might_rain=f.get('positionHigher') > 0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return forecast
|
return forecast
|
||||||
|
|
||||||
async def daily_list_to_forecast(self, data: List[dict] | None) -> List[Forecast] | None:
|
async def daily_list_to_forecast(self, data: List[dict] | None) -> List[IrmKmiForecast] | None:
|
||||||
"""Parse data from the API to create a list of daily forecasts"""
|
"""Parse data from the API to create a list of daily forecasts"""
|
||||||
if data is None or not isinstance(data, list) or len(data) == 0:
|
if data is None or not isinstance(data, list) or len(data) == 0:
|
||||||
return None
|
return None
|
||||||
|
@ -403,6 +405,28 @@ class IrmKmiCoordinator(TimestampDataUpdateCoordinator):
|
||||||
elif day_name == 'Tomorrow':
|
elif day_name == 'Tomorrow':
|
||||||
forecast_day = dt.now(tz) + timedelta(days=1)
|
forecast_day = dt.now(tz) + timedelta(days=1)
|
||||||
|
|
||||||
|
sunrise_sec = f.get('dawnRiseSeconds', None)
|
||||||
|
if sunrise_sec is None:
|
||||||
|
sunrise_sec = f.get('sunRise', None)
|
||||||
|
sunrise = None
|
||||||
|
if sunrise_sec is not None:
|
||||||
|
try:
|
||||||
|
sunrise = (forecast_day.replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=tz)
|
||||||
|
+ timedelta(seconds=float(sunrise_sec)))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
sunset_sec = f.get('dawnSetSeconds', None)
|
||||||
|
if sunset_sec is None:
|
||||||
|
sunset_sec = f.get('sunSet', None)
|
||||||
|
sunset = None
|
||||||
|
if sunset_sec is not None:
|
||||||
|
try:
|
||||||
|
sunset = (forecast_day.replace(hour=0, minute=0, second=0, microsecond=0, tzinfo=tz)
|
||||||
|
+ timedelta(seconds=float(sunset_sec)))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
forecast = IrmKmiForecast(
|
forecast = IrmKmiForecast(
|
||||||
datetime=(forecast_day.strftime('%Y-%m-%d')),
|
datetime=(forecast_day.strftime('%Y-%m-%d')),
|
||||||
condition=CDT_MAP.get((f.get('ww1', None), f.get('dayNight', None)), None),
|
condition=CDT_MAP.get((f.get('ww1', None), f.get('dayNight', None)), None),
|
||||||
|
@ -415,6 +439,8 @@ class IrmKmiCoordinator(TimestampDataUpdateCoordinator):
|
||||||
wind_bearing=wind_bearing,
|
wind_bearing=wind_bearing,
|
||||||
is_daytime=is_daytime,
|
is_daytime=is_daytime,
|
||||||
text=f.get('text', {}).get(lang, ""),
|
text=f.get('text', {}).get(lang, ""),
|
||||||
|
sunrise=sunrise,
|
||||||
|
sunset=sunset
|
||||||
)
|
)
|
||||||
# Swap temperature and templow if needed
|
# Swap temperature and templow if needed
|
||||||
if (forecast['native_templow'] is not None
|
if (forecast['native_templow'] is not None
|
||||||
|
|
|
@ -10,6 +10,8 @@ class IrmKmiForecast(Forecast):
|
||||||
|
|
||||||
# TODO: add condition_2 as well and evolution to match data from the API?
|
# TODO: add condition_2 as well and evolution to match data from the API?
|
||||||
text: str | None
|
text: str | None
|
||||||
|
sunrise: datetime | None
|
||||||
|
sunset: datetime | None
|
||||||
|
|
||||||
|
|
||||||
class IrmKmiRadarForecast(Forecast):
|
class IrmKmiRadarForecast(Forecast):
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import zoneinfo
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
|
@ -101,7 +102,7 @@ async def test_daily_forecast(
|
||||||
assert len(result) == 8
|
assert len(result) == 8
|
||||||
assert result[0]['datetime'] == '2023-12-26'
|
assert result[0]['datetime'] == '2023-12-26'
|
||||||
assert not result[0]['is_daytime']
|
assert not result[0]['is_daytime']
|
||||||
|
tz = zoneinfo.ZoneInfo(key='Europe/Brussels')
|
||||||
expected = IrmKmiForecast(
|
expected = IrmKmiForecast(
|
||||||
datetime='2023-12-27',
|
datetime='2023-12-27',
|
||||||
condition=ATTR_CONDITION_PARTLYCLOUDY,
|
condition=ATTR_CONDITION_PARTLYCLOUDY,
|
||||||
|
@ -114,6 +115,8 @@ async def test_daily_forecast(
|
||||||
wind_bearing=180,
|
wind_bearing=180,
|
||||||
is_daytime=True,
|
is_daytime=True,
|
||||||
text='Bar',
|
text='Bar',
|
||||||
|
sunrise=datetime.fromisoformat("2023-12-27T08:44:00+01:00").astimezone(tz),
|
||||||
|
sunset=datetime.fromisoformat("2023-12-27T16:43:00+01:00").astimezone(tz)
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result[1] == expected
|
assert result[1] == expected
|
||||||
|
@ -350,3 +353,40 @@ async def test_current_condition_forecast_nl() -> None:
|
||||||
uv_index=6
|
uv_index=6
|
||||||
)
|
)
|
||||||
assert result == expected
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
|
@freeze_time("2024-06-09T13:40:00+00:00")
|
||||||
|
async def test_sunrise_sunset_nl(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
api_data = get_api_data("forecast_ams_no_ww.json").get('for', {}).get('daily')
|
||||||
|
|
||||||
|
coordinator = IrmKmiCoordinator(hass, mock_config_entry)
|
||||||
|
result = await coordinator.daily_list_to_forecast(api_data)
|
||||||
|
|
||||||
|
assert result[0]['sunrise'].isoformat() == '2024-06-09T05:19:28+02:00'
|
||||||
|
assert result[0]['sunset'].isoformat() == '2024-06-09T22:01:09+02:00'
|
||||||
|
|
||||||
|
assert result[1]['sunrise'] is None
|
||||||
|
assert result[1]['sunset'] is None
|
||||||
|
|
||||||
|
assert result[2]['sunrise'].isoformat() == '2024-06-10T05:19:08+02:00'
|
||||||
|
assert result[2]['sunset'].isoformat() == '2024-06-10T22:01:53+02:00'
|
||||||
|
|
||||||
|
|
||||||
|
@freeze_time("2023-12-26T18:30:00+01:00")
|
||||||
|
async def test_sunrise_sunset_be(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_config_entry: MockConfigEntry
|
||||||
|
) -> None:
|
||||||
|
api_data = get_api_data("forecast.json").get('for', {}).get('daily')
|
||||||
|
|
||||||
|
coordinator = IrmKmiCoordinator(hass, mock_config_entry)
|
||||||
|
result = await coordinator.daily_list_to_forecast(api_data)
|
||||||
|
|
||||||
|
assert result[1]['sunrise'].isoformat() == '2023-12-27T08:44:00+01:00'
|
||||||
|
assert result[1]['sunset'].isoformat() == '2023-12-27T16:43:00+01:00'
|
||||||
|
|
||||||
|
assert result[2]['sunrise'].isoformat() == '2023-12-28T08:45:00+01:00'
|
||||||
|
assert result[2]['sunset'].isoformat() == '2023-12-28T16:43:00+01:00'
|
||||||
|
|
Loading…
Add table
Reference in a new issue