Compare commits

...

6 commits

17 changed files with 404 additions and 42 deletions

View file

@ -1,6 +1,7 @@
"""Constants for the IRM KMI integration.""" """Constants for the IRM KMI integration."""
from typing import Final from typing import Final
from homeassistant.components.sensor import SensorDeviceClass
from homeassistant.components.weather import (ATTR_CONDITION_CLEAR_NIGHT, from homeassistant.components.weather import (ATTR_CONDITION_CLEAR_NIGHT,
ATTR_CONDITION_CLOUDY, ATTR_CONDITION_CLOUDY,
ATTR_CONDITION_FOG, ATTR_CONDITION_FOG,
@ -11,7 +12,7 @@ from homeassistant.components.weather import (ATTR_CONDITION_CLEAR_NIGHT,
ATTR_CONDITION_SNOWY, ATTR_CONDITION_SNOWY,
ATTR_CONDITION_SNOWY_RAINY, ATTR_CONDITION_SNOWY_RAINY,
ATTR_CONDITION_SUNNY) ATTR_CONDITION_SUNNY)
from homeassistant.const import Platform from homeassistant.const import Platform, UnitOfPressure, UnitOfSpeed, UnitOfTemperature, DEGREE
DOMAIN: Final = 'irm_kmi' DOMAIN: Final = 'irm_kmi'
PLATFORMS: Final = [Platform.WEATHER, Platform.CAMERA, Platform.BINARY_SENSOR, Platform.SENSOR] PLATFORMS: Final = [Platform.WEATHER, Platform.CAMERA, Platform.BINARY_SENSOR, Platform.SENSOR]
@ -160,4 +161,29 @@ IRM_KMI_NAME: Final = {
WEEKDAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] WEEKDAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
USER_AGENT: Final = 'github.com/jdejaegh/irm-kmi-ha 0.2.29' USER_AGENT: Final = 'github.com/jdejaegh/irm-kmi-ha 0.2.30'
CURRENT_WEATHER_SENSORS: Final = {'temperature', 'wind_speed', 'wind_gust_speed', 'wind_bearing', 'uv_index',
'pressure'}
CURRENT_WEATHER_SENSOR_UNITS: Final = {'temperature': UnitOfTemperature.CELSIUS,
'wind_speed': UnitOfSpeed.KILOMETERS_PER_HOUR,
'wind_gust_speed': UnitOfSpeed.KILOMETERS_PER_HOUR,
'wind_bearing': DEGREE,
'uv_index': None,
'pressure': UnitOfPressure.HPA}
CURRENT_WEATHER_SENSOR_CLASS: Final = {'temperature': SensorDeviceClass.TEMPERATURE,
'wind_speed': SensorDeviceClass.WIND_SPEED,
'wind_gust_speed': SensorDeviceClass.WIND_SPEED,
'wind_bearing': None,
'uv_index': None,
'pressure': SensorDeviceClass.ATMOSPHERIC_PRESSURE}
# Leave None when we want the default icon to be shown
CURRENT_WEATHER_SENSOR_ICON: Final = {'temperature': None,
'wind_speed': None,
'wind_gust_speed': None,
'wind_bearing': 'mdi:compass',
'uv_index': 'mdi:sun-wireless',
'pressure': None}

View file

@ -327,6 +327,7 @@ class IrmKmiCoordinator(TimestampDataUpdateCoordinator):
if data is None: if data is None:
return None return None
sequence = data.get("sequence", []) sequence = data.get("sequence", [])
unit = data.get("unit", {}).get("en", None)
ratios = [f['value'] / f['position'] for f in sequence if f['position'] > 0] ratios = [f['value'] / f['position'] for f in sequence if f['position'] > 0]
if len(ratios) > 0: if len(ratios) > 0:
@ -342,7 +343,8 @@ class IrmKmiCoordinator(TimestampDataUpdateCoordinator):
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,
unit=unit
) )
) )
return forecast return forecast

View file

@ -12,5 +12,5 @@
"svgwrite==1.4.3", "svgwrite==1.4.3",
"aiofile==3.9.0" "aiofile==3.9.0"
], ],
"version": "0.2.29" "version": "0.2.30"
} }

View file

@ -11,6 +11,7 @@ class IrmKmiRadarForecast(Forecast):
rain_forecast_max: float rain_forecast_max: float
rain_forecast_min: float rain_forecast_min: float
might_rain: bool might_rain: bool
unit: str | None
class AnimationFrameData(TypedDict, total=False): class AnimationFrameData(TypedDict, total=False):

View file

@ -11,9 +11,11 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util import dt from homeassistant.util import dt
from custom_components.irm_kmi import DOMAIN, IrmKmiCoordinator from custom_components.irm_kmi import DOMAIN, IrmKmiCoordinator
from custom_components.irm_kmi.const import POLLEN_NAMES, POLLEN_TO_ICON_MAP from custom_components.irm_kmi.const import POLLEN_NAMES, POLLEN_TO_ICON_MAP, CURRENT_WEATHER_SENSOR_UNITS, \
CURRENT_WEATHER_SENSOR_CLASS, CURRENT_WEATHER_SENSORS, CURRENT_WEATHER_SENSOR_ICON
from custom_components.irm_kmi.data import IrmKmiForecast from custom_components.irm_kmi.data import IrmKmiForecast
from custom_components.irm_kmi.pollen import PollenParser from custom_components.irm_kmi.pollen import PollenParser
from custom_components.irm_kmi.radar_data import IrmKmiRadarForecast
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -22,7 +24,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e
"""Set up the sensor platform""" """Set up the sensor platform"""
coordinator = hass.data[DOMAIN][entry.entry_id] coordinator = hass.data[DOMAIN][entry.entry_id]
async_add_entities([IrmKmiPollen(coordinator, entry, pollen.lower()) for pollen in POLLEN_NAMES]) async_add_entities([IrmKmiPollen(coordinator, entry, pollen.lower()) for pollen in POLLEN_NAMES])
async_add_entities([IrmKmiNextWarning(coordinator, entry),]) async_add_entities([IrmKmiCurrentWeather(coordinator, entry, name) for name in CURRENT_WEATHER_SENSORS])
async_add_entities([IrmKmiNextWarning(coordinator, entry),
IrmKmiCurrentRainfall(coordinator, entry)])
if coordinator.data.get('country') != 'NL': if coordinator.data.get('country') != 'NL':
async_add_entities([IrmKmiNextSunMove(coordinator, entry, move) for move in ['sunset', 'sunrise']]) async_add_entities([IrmKmiNextSunMove(coordinator, entry, move) for move in ['sunset', 'sunrise']])
@ -135,3 +139,91 @@ class IrmKmiNextSunMove(CoordinatorEntity, SensorEntity):
if len(upcoming) > 0: if len(upcoming) > 0:
return upcoming[0] return upcoming[0]
return None return None
class IrmKmiCurrentWeather(CoordinatorEntity, SensorEntity):
"""Representation of a current weather sensor"""
_attr_has_entity_name = True
_attr_attribution = "Weather data from the Royal Meteorological Institute of Belgium meteo.be"
def __init__(self,
coordinator: IrmKmiCoordinator,
entry: ConfigEntry,
sensor_name: str) -> None:
super().__init__(coordinator)
SensorEntity.__init__(self)
self._attr_unique_id = f"{entry.entry_id}-current-{sensor_name}"
self.entity_id = sensor.ENTITY_ID_FORMAT.format(f"{str(entry.title).lower()}_current_{sensor_name}")
self._attr_device_info = coordinator.shared_device_info
self._attr_translation_key = f"current_{sensor_name}"
self._sensor_name: str = sensor_name
@property
def native_value(self) -> float | None:
"""Return the current value of the sensor"""
return self.coordinator.data.get('current_weather', {}).get(self._sensor_name, None)
@property
def native_unit_of_measurement(self) -> str | None:
return CURRENT_WEATHER_SENSOR_UNITS[self._sensor_name]
@property
def device_class(self) -> SensorDeviceClass | None:
return CURRENT_WEATHER_SENSOR_CLASS[self._sensor_name]
@property
def icon(self) -> str | None:
return CURRENT_WEATHER_SENSOR_ICON[self._sensor_name]
class IrmKmiCurrentRainfall(CoordinatorEntity, SensorEntity):
"""Representation of a current rainfall sensor"""
_attr_has_entity_name = True
_attr_attribution = "Weather data from the Royal Meteorological Institute of Belgium meteo.be"
def __init__(self,
coordinator: IrmKmiCoordinator,
entry: ConfigEntry) -> None:
super().__init__(coordinator)
SensorEntity.__init__(self)
self._attr_unique_id = f"{entry.entry_id}-current-rainfall"
self.entity_id = sensor.ENTITY_ID_FORMAT.format(f"{str(entry.title).lower()}_current_rainfall")
self._attr_device_info = coordinator.shared_device_info
self._attr_translation_key = "current_rainfall"
self._attr_icon = 'mdi:weather-pouring'
def _current_forecast(self) -> IrmKmiRadarForecast | None:
now = dt.now()
forecasts = self.coordinator.data.get('radar_forecast', None)
if forecasts is None:
return None
prev = forecasts[0]
for f in forecasts:
if datetime.fromisoformat(f.get('datetime')) > now:
return prev
prev = f
return forecasts[-1]
@property
def native_value(self) -> float | None:
"""Return the current value of the sensor"""
current = self._current_forecast()
if current is None:
return None
return current.get('native_precipitation', None)
@property
def native_unit_of_measurement(self) -> str | None:
current = self._current_forecast()
if current is None:
return None
return current.get('unit', None)

View file

@ -182,6 +182,27 @@
"purple": "Purple", "purple": "Purple",
"none": "None" "none": "None"
} }
},
"current_temperature": {
"name": "Temperature"
},
"current_wind_speed": {
"name": "Wind speed"
},
"current_wind_gust_speed": {
"name": "Wind gust speed"
},
"current_wind_bearing": {
"name": "Wind bearing"
},
"current_uv_index": {
"name": "UV index"
},
"current_pressure": {
"name": "Atmospheric pressure"
},
"current_rainfall": {
"name": "Rainfall"
} }
} }
}, },

View file

@ -182,6 +182,27 @@
"purple": "Violet", "purple": "Violet",
"none": "Aucun" "none": "Aucun"
} }
},
"current_temperature": {
"name": "Température"
},
"current_wind_speed": {
"name": "Vitesse du vent"
},
"current_wind_gust_speed": {
"name": "Vitesse des rafales de vent"
},
"current_wind_bearing": {
"name": "Direction du vent"
},
"current_uv_index": {
"name": "Index UV"
},
"current_pressure": {
"name": "Pression atmosphérique"
},
"current_rainfall": {
"name": "Precipitation"
} }
} }
}, },

View file

@ -182,6 +182,27 @@
"purple": "Paars", "purple": "Paars",
"none": "Geen" "none": "Geen"
} }
},
"current_temperature": {
"name": "Temperatuur"
},
"current_wind_speed": {
"name": "Windsnelheid"
},
"current_wind_gust_speed": {
"name": "Snelheid windvlaag"
},
"current_wind_bearing": {
"name": "Windrichting"
},
"current_uv_index": {
"name": "UV-index"
},
"current_pressure": {
"name": "Luchtdruk"
},
"current_rainfall": {
"name": "Neerslag"
} }
} }
}, },

View file

@ -182,6 +182,27 @@
"purple": "Roxo", "purple": "Roxo",
"none": "Nenhum" "none": "Nenhum"
} }
},
"current_temperature": {
"name": "Temperatura"
},
"current_wind_speed": {
"name": "Velocidade do vento"
},
"current_wind_gust_speed": {
"name": "Velocidade da rajada de vento"
},
"current_wind_bearing": {
"name": "Direção do vento"
},
"current_uv_index": {
"name": "Índice UV"
},
"current_pressure": {
"name": "Pressão atmosférica"
},
"current_rainfall": {
"name": "Precipitação"
} }
} }
}, },

View file

@ -1,5 +1,5 @@
[tool.bumpver] [tool.bumpver]
current_version = "0.2.29" current_version = "0.2.30"
version_pattern = "MAJOR.MINOR.PATCH" version_pattern = "MAJOR.MINOR.PATCH"
commit_message = "bump version {old_version} -> {new_version}" commit_message = "bump version {old_version} -> {new_version}"
tag_message = "{new_version}" tag_message = "{new_version}"

View file

@ -1474,7 +1474,7 @@
{ {
"time": "2024-01-12T10:10:00+01:00", "time": "2024-01-12T10:10:00+01:00",
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202401120920&f=2&k=2160a92594985471351907ee5cc75d1f&d=202401120900", "uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202401120920&f=2&k=2160a92594985471351907ee5cc75d1f&d=202401120900",
"value": 0, "value": 0.42,
"position": 0, "position": 0,
"positionLower": 0, "positionLower": 0,
"positionHigher": 0 "positionHigher": 0

View file

@ -1642,7 +1642,7 @@
{ {
"time": "2024-06-09T13:40:00+00:00", "time": "2024-06-09T13:40:00+00:00",
"uri": "https:\/\/cdn.knmi.nl\/knmi\/map\/page\/weer\/actueel-weer\/neerslagradar\/weerapp\/RAD_NL25_PCP_CM_202406091340_640.png", "uri": "https:\/\/cdn.knmi.nl\/knmi\/map\/page\/weer\/actueel-weer\/neerslagradar\/weerapp\/RAD_NL25_PCP_CM_202406091340_640.png",
"value": 0, "value": 0.1341,
"position": 0, "position": 0,
"positionLower": 0, "positionLower": 0,
"positionHigher": 0 "positionHigher": 0

View file

@ -6,7 +6,7 @@
"municipality_code": "0995", "municipality_code": "0995",
"temp": 11, "temp": 11,
"windSpeedKm": 40, "windSpeedKm": 40,
"timestamp": "2023-12-28T14:20:00+00:00", "timestamp": "2023-12-28T14:30:00+00:00",
"windDirection": 45, "windDirection": 45,
"municipality": "Lelystad", "municipality": "Lelystad",
"windDirectionText": { "windDirectionText": {
@ -1337,7 +1337,7 @@
{ {
"time": "2023-12-28T14:25:00+00:00", "time": "2023-12-28T14:25:00+00:00",
"uri": "https:\/\/cdn.knmi.nl\/knmi\/map\/page\/weer\/actueel-weer\/neerslagradar\/weerapp\/RAD_NL25_PCP_CM_202312281425_640.png", "uri": "https:\/\/cdn.knmi.nl\/knmi\/map\/page\/weer\/actueel-weer\/neerslagradar\/weerapp\/RAD_NL25_PCP_CM_202312281425_640.png",
"value": 0, "value": 0.15,
"position": 0, "position": 0,
"positionLower": 0, "positionLower": 0,
"positionHigher": 0 "positionHigher": 0

View file

@ -1,4 +1,3 @@
import zoneinfo
from datetime import datetime, timedelta from datetime import datetime, timedelta
from freezegun import freeze_time from freezegun import freeze_time
@ -12,9 +11,8 @@ from custom_components.irm_kmi.const import CONF_LANGUAGE_OVERRIDE
from custom_components.irm_kmi.coordinator import IrmKmiCoordinator from custom_components.irm_kmi.coordinator import IrmKmiCoordinator
from custom_components.irm_kmi.data import (CurrentWeatherData, IrmKmiForecast, from custom_components.irm_kmi.data import (CurrentWeatherData, IrmKmiForecast,
ProcessedCoordinatorData) ProcessedCoordinatorData)
from custom_components.irm_kmi.radar_data import IrmKmiRadarForecast, RadarAnimationData
from custom_components.irm_kmi.pollen import PollenParser from custom_components.irm_kmi.pollen import PollenParser
from custom_components.irm_kmi.rain_graph import RainGraph from custom_components.irm_kmi.radar_data import IrmKmiRadarForecast
from tests.conftest import get_api_data from tests.conftest import get_api_data
@ -267,27 +265,27 @@ def test_radar_forecast() -> None:
expected = [ expected = [
IrmKmiRadarForecast(datetime="2023-12-26T17:00:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:00:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:10:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:10:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:20:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:20:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:30:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:30:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:40:00+01:00", native_precipitation=0.1, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:40:00+01:00", native_precipitation=0.1, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:50:00+01:00", native_precipitation=0.01, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:50:00+01:00", native_precipitation=0.01, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:00:00+01:00", native_precipitation=0.12, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:00:00+01:00", native_precipitation=0.12, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:10:00+01:00", native_precipitation=1.2, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:10:00+01:00", native_precipitation=1.2, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:20:00+01:00", native_precipitation=2, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:20:00+01:00", native_precipitation=2, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:30:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:30:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:40:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:40:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0) rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min')
] ]
assert expected == result assert expected == result
@ -302,7 +300,8 @@ def test_radar_forecast_rain_interval() -> None:
native_precipitation=0.89, native_precipitation=0.89,
might_rain=True, might_rain=True,
rain_forecast_max=1.12, rain_forecast_max=1.12,
rain_forecast_min=0.50 rain_forecast_min=0.50,
unit='mm/10min'
) )
_13 = IrmKmiRadarForecast( _13 = IrmKmiRadarForecast(
@ -310,7 +309,8 @@ def test_radar_forecast_rain_interval() -> None:
native_precipitation=0.83, native_precipitation=0.83,
might_rain=True, might_rain=True,
rain_forecast_max=1.09, rain_forecast_max=1.09,
rain_forecast_min=0.64 rain_forecast_min=0.64,
unit='mm/10min'
) )
assert result[12] == _12 assert result[12] == _12

View file

@ -0,0 +1,159 @@
import inspect
from datetime import datetime, timedelta
import pytest
from freezegun import freeze_time
from homeassistant.core import HomeAssistant
from pytest_homeassistant_custom_component.common import MockConfigEntry
from custom_components.irm_kmi import IrmKmiCoordinator
from custom_components.irm_kmi.const import CURRENT_WEATHER_SENSORS, CURRENT_WEATHER_SENSOR_UNITS, \
CURRENT_WEATHER_SENSOR_CLASS
from custom_components.irm_kmi.data import CurrentWeatherData, ProcessedCoordinatorData
from custom_components.irm_kmi.sensor import IrmKmiCurrentWeather, IrmKmiCurrentRainfall
from tests.conftest import get_api_data
def test_sensors_in_current_weather_data():
weather_data_keys = inspect.get_annotations(CurrentWeatherData).keys()
for sensor in CURRENT_WEATHER_SENSORS:
assert sensor in weather_data_keys
def test_sensors_have_unit():
weather_sensor_units_keys = CURRENT_WEATHER_SENSOR_UNITS.keys()
for sensor in CURRENT_WEATHER_SENSORS:
assert sensor in weather_sensor_units_keys
def test_sensors_have_class():
weather_sensor_class_keys = CURRENT_WEATHER_SENSOR_CLASS.keys()
for sensor in CURRENT_WEATHER_SENSORS:
assert sensor in weather_sensor_class_keys
@pytest.mark.parametrize("sensor,expected,filename",
[
('temperature', -2, 'be_forecast_warning.json'),
('temperature', 7, 'forecast.json'),
('temperature', 15, 'forecast_ams_no_ww.json'),
('temperature', 9, 'forecast_out_of_benelux.json'),
('temperature', 13, 'forecast_with_rain_on_radar.json'),
('temperature', 4, 'high_low_temp.json'),
('temperature', 14, 'midnight-bug-31-05-2024T00-13.json'),
('temperature', 13, 'no-midnight-bug-31-05-2024T01-55.json'),
('wind_speed', 10, 'be_forecast_warning.json'),
('wind_speed', 5, 'forecast.json'),
('wind_speed', 26, 'forecast_ams_no_ww.json'),
('wind_speed', 25, 'forecast_out_of_benelux.json'),
('wind_speed', 15, 'forecast_with_rain_on_radar.json'),
('wind_speed', 30, 'high_low_temp.json'),
('wind_speed', 10, 'midnight-bug-31-05-2024T00-13.json'),
('wind_speed', 15, 'no-midnight-bug-31-05-2024T01-55.json'),
('wind_gust_speed', None, 'be_forecast_warning.json'),
('wind_gust_speed', None, 'forecast.json'),
('wind_gust_speed', None, 'forecast_ams_no_ww.json'),
('wind_gust_speed', None, 'forecast_out_of_benelux.json'),
('wind_gust_speed', None, 'forecast_with_rain_on_radar.json'),
('wind_gust_speed', 50, 'high_low_temp.json'),
('wind_gust_speed', None, 'midnight-bug-31-05-2024T00-13.json'),
('wind_gust_speed', None, 'no-midnight-bug-31-05-2024T01-55.json'),
('wind_bearing', 23, 'be_forecast_warning.json'),
('wind_bearing', 248, 'forecast.json'),
('wind_bearing', 270, 'forecast_ams_no_ww.json'),
('wind_bearing', 180, 'forecast_out_of_benelux.json'),
('wind_bearing', 293, 'forecast_with_rain_on_radar.json'),
('wind_bearing', 180, 'high_low_temp.json'),
('wind_bearing', 293, 'midnight-bug-31-05-2024T00-13.json'),
('wind_bearing', 270, 'no-midnight-bug-31-05-2024T01-55.json'),
('uv_index', 0.7, 'be_forecast_warning.json'),
('uv_index', 0.7, 'forecast.json'),
('uv_index', 6, 'forecast_ams_no_ww.json'),
('uv_index', 0.6, 'forecast_out_of_benelux.json'),
('uv_index', None, 'forecast_with_rain_on_radar.json'),
('uv_index', 0.7, 'high_low_temp.json'),
('uv_index', 5.6, 'midnight-bug-31-05-2024T00-13.json'),
('uv_index', 5.6, 'no-midnight-bug-31-05-2024T01-55.json'),
('pressure', 1034, 'be_forecast_warning.json'),
('pressure', 1020, 'forecast.json'),
('pressure', 1010, 'forecast_ams_no_ww.json'),
('pressure', 1013, 'forecast_out_of_benelux.json'),
('pressure', 1006, 'forecast_with_rain_on_radar.json'),
('pressure', 1022, 'high_low_temp.json'),
('pressure', 1010, 'midnight-bug-31-05-2024T00-13.json'),
('pressure', 1010, 'no-midnight-bug-31-05-2024T01-55.json'),
('rainfall', 0.42, 'be_forecast_warning.json'),
('rainfall', 0.15, 'forecast_nl.json'),
('rainfall', 0, 'forecast.json'),
('rainfall', 0.1341, 'forecast_ams_no_ww.json'),
('rainfall', 0, 'forecast_out_of_benelux.json'),
('rainfall', 0.33, 'forecast_with_rain_on_radar.json'),
('rainfall', 0, 'high_low_temp.json'),
('rainfall', 0, 'midnight-bug-31-05-2024T00-13.json'),
('rainfall', 0, 'no-midnight-bug-31-05-2024T01-55.json'),
])
async def test_current_weather_sensors(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
sensor,
expected,
filename
) -> None:
hass.config.time_zone = 'Europe/Brussels'
api_data = get_api_data(filename)
time = api_data.get('obs').get('timestamp')
@freeze_time(datetime.fromisoformat(time) + timedelta(seconds=45, minutes=1))
async def run(mock_config_entry_, sensor_, expected_):
coordinator = IrmKmiCoordinator(hass, mock_config_entry_)
coordinator.data = ProcessedCoordinatorData(
current_weather=await IrmKmiCoordinator.current_weather_from_data(api_data),
hourly_forecast=await IrmKmiCoordinator.hourly_list_to_forecast(api_data.get('for', {}).get('hourly')),
radar_forecast=IrmKmiCoordinator.radar_list_to_forecast(api_data.get('animation', {})),
country=api_data.get('country')
)
if sensor_ == 'rainfall':
s = IrmKmiCurrentRainfall(coordinator, mock_config_entry_)
else:
s = IrmKmiCurrentWeather(coordinator, mock_config_entry_, sensor_)
assert s.native_value == expected_
await run(mock_config_entry, sensor, expected)
@pytest.mark.parametrize("expected,filename",
[
('mm/h', 'forecast_ams_no_ww.json'),
('mm/10min', 'forecast_out_of_benelux.json'),
('mm/10min', 'forecast_with_rain_on_radar.json'),
])
async def test_current_rainfall_unit(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
expected,
filename
) -> None:
hass.config.time_zone = 'Europe/Brussels'
coordinator = IrmKmiCoordinator(hass, mock_config_entry)
api_data = get_api_data(filename)
coordinator.data = ProcessedCoordinatorData(
current_weather=await IrmKmiCoordinator.current_weather_from_data(api_data),
hourly_forecast=await IrmKmiCoordinator.hourly_list_to_forecast(api_data.get('for', {}).get('hourly')),
radar_forecast=IrmKmiCoordinator.radar_list_to_forecast(api_data.get('animation', {})),
country=api_data.get('country')
)
s = IrmKmiCurrentRainfall(coordinator, mock_config_entry)
assert s.native_unit_of_measurement == expected

View file

@ -7,8 +7,7 @@ from pytest_homeassistant_custom_component.common import MockConfigEntry
from custom_components.irm_kmi import IrmKmiCoordinator from custom_components.irm_kmi import IrmKmiCoordinator
from custom_components.irm_kmi.binary_sensor import IrmKmiWarning from custom_components.irm_kmi.binary_sensor import IrmKmiWarning
from custom_components.irm_kmi.const import CONF_LANGUAGE_OVERRIDE from custom_components.irm_kmi.const import CONF_LANGUAGE_OVERRIDE
from custom_components.irm_kmi.sensor import (IrmKmiNextSunMove, from custom_components.irm_kmi.sensor import IrmKmiNextSunMove, IrmKmiNextWarning
IrmKmiNextWarning)
from tests.conftest import get_api_data from tests.conftest import get_api_data

View file

@ -5,7 +5,6 @@ from unittest.mock import AsyncMock
from freezegun import freeze_time from freezegun import freeze_time
from homeassistant.components.weather import Forecast from homeassistant.components.weather import Forecast
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from pytest_homeassistant_custom_component.common import MockConfigEntry from pytest_homeassistant_custom_component.common import MockConfigEntry
@ -30,7 +29,7 @@ async def test_weather_nl(
coordinator = IrmKmiCoordinator(hass, mock_config_entry) coordinator = IrmKmiCoordinator(hass, mock_config_entry)
await coordinator.async_refresh() await coordinator.async_refresh()
print(coordinator.data)
weather = IrmKmiWeather(coordinator, mock_config_entry) weather = IrmKmiWeather(coordinator, mock_config_entry)
result = await weather.async_forecast_daily() result = await weather.async_forecast_daily()
@ -118,27 +117,27 @@ async def test_radar_forecast_service(
expected = [ expected = [
IrmKmiRadarForecast(datetime="2023-12-26T17:00:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:00:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:10:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:10:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:20:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:20:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:30:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:30:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:40:00+01:00", native_precipitation=0.1, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:40:00+01:00", native_precipitation=0.1, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T17:50:00+01:00", native_precipitation=0.01, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T17:50:00+01:00", native_precipitation=0.01, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:00:00+01:00", native_precipitation=0.12, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:00:00+01:00", native_precipitation=0.12, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:10:00+01:00", native_precipitation=1.2, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:10:00+01:00", native_precipitation=1.2, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:20:00+01:00", native_precipitation=2, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:20:00+01:00", native_precipitation=2, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:30:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:30:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0), rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min'),
IrmKmiRadarForecast(datetime="2023-12-26T18:40:00+01:00", native_precipitation=0, might_rain=False, IrmKmiRadarForecast(datetime="2023-12-26T18:40:00+01:00", native_precipitation=0, might_rain=False,
rain_forecast_max=0, rain_forecast_min=0) rain_forecast_max=0, rain_forecast_min=0, unit='mm/10min')
] ]
assert result_service == expected[5:] assert result_service == expected[5:]