diff --git a/CODEOWNERS b/CODEOWNERS index a0f5171dd49..0b6a1a8177f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -772,6 +772,8 @@ build.json @home-assistant/supervisor /homeassistant/components/iqvia/ @bachya /tests/components/iqvia/ @bachya /homeassistant/components/irish_rail_transport/ @ttroy50 +/homeassistant/components/irm_kmi/ @jdejaegh +/tests/components/irm_kmi/ @jdejaegh /homeassistant/components/iron_os/ @tr4nt0r /tests/components/iron_os/ @tr4nt0r /homeassistant/components/isal/ @bdraco diff --git a/homeassistant/components/irm_kmi/__init__.py b/homeassistant/components/irm_kmi/__init__.py new file mode 100644 index 00000000000..3ca71f61cd6 --- /dev/null +++ b/homeassistant/components/irm_kmi/__init__.py @@ -0,0 +1,40 @@ +"""Integration for IRM KMI weather.""" + +import logging + +from irm_kmi_api import IrmKmiApiClientHa + +from homeassistant.core import HomeAssistant +from homeassistant.helpers.aiohttp_client import async_get_clientsession + +from .const import IRM_KMI_TO_HA_CONDITION_MAP, PLATFORMS, USER_AGENT +from .coordinator import IrmKmiConfigEntry, IrmKmiCoordinator + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry(hass: HomeAssistant, entry: IrmKmiConfigEntry) -> bool: + """Set up this integration using UI.""" + api_client = IrmKmiApiClientHa( + session=async_get_clientsession(hass), + user_agent=USER_AGENT, + cdt_map=IRM_KMI_TO_HA_CONDITION_MAP, + ) + + entry.runtime_data = IrmKmiCoordinator(hass, entry, api_client) + + await entry.runtime_data.async_config_entry_first_refresh() + + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + + return True + + +async def async_unload_entry(hass: HomeAssistant, entry: IrmKmiConfigEntry) -> bool: + """Handle removal of an entry.""" + return await hass.config_entries.async_unload_platforms(entry, PLATFORMS) + + +async def async_reload_entry(hass: HomeAssistant, entry: IrmKmiConfigEntry) -> None: + """Reload config entry.""" + await hass.config_entries.async_reload(entry.entry_id) diff --git a/homeassistant/components/irm_kmi/config_flow.py b/homeassistant/components/irm_kmi/config_flow.py new file mode 100644 index 00000000000..ad426b36ba5 --- /dev/null +++ b/homeassistant/components/irm_kmi/config_flow.py @@ -0,0 +1,132 @@ +"""Config flow to set up IRM KMI integration via the UI.""" + +import logging + +from irm_kmi_api import IrmKmiApiClient, IrmKmiApiError +import voluptuous as vol + +from homeassistant.config_entries import ( + ConfigFlow, + ConfigFlowResult, + OptionsFlow, + OptionsFlowWithReload, +) +from homeassistant.const import ( + ATTR_LATITUDE, + ATTR_LONGITUDE, + CONF_LOCATION, + CONF_UNIQUE_ID, +) +from homeassistant.core import callback +from homeassistant.helpers.aiohttp_client import async_get_clientsession +from homeassistant.helpers.selector import ( + LocationSelector, + SelectSelector, + SelectSelectorConfig, + SelectSelectorMode, +) + +from .const import ( + CONF_LANGUAGE_OVERRIDE, + CONF_LANGUAGE_OVERRIDE_OPTIONS, + DOMAIN, + OUT_OF_BENELUX, + USER_AGENT, +) +from .coordinator import IrmKmiConfigEntry + +_LOGGER = logging.getLogger(__name__) + + +class IrmKmiConfigFlow(ConfigFlow, domain=DOMAIN): + """Configuration flow for the IRM KMI integration.""" + + VERSION = 1 + + @staticmethod + @callback + def async_get_options_flow(_config_entry: IrmKmiConfigEntry) -> OptionsFlow: + """Create the options flow.""" + return IrmKmiOptionFlow() + + async def async_step_user(self, user_input: dict | None = None) -> ConfigFlowResult: + """Define the user step of the configuration flow.""" + errors: dict = {} + + default_location = { + ATTR_LATITUDE: self.hass.config.latitude, + ATTR_LONGITUDE: self.hass.config.longitude, + } + + if user_input: + _LOGGER.debug("Provided config user is: %s", user_input) + + lat: float = user_input[CONF_LOCATION][ATTR_LATITUDE] + lon: float = user_input[CONF_LOCATION][ATTR_LONGITUDE] + + try: + api_data = await IrmKmiApiClient( + session=async_get_clientsession(self.hass), + user_agent=USER_AGENT, + ).get_forecasts_coord({"lat": lat, "long": lon}) + except IrmKmiApiError: + _LOGGER.exception( + "Encountered an unexpected error while configuring the integration" + ) + return self.async_abort(reason="api_error") + + if api_data["cityName"] in OUT_OF_BENELUX: + errors[CONF_LOCATION] = "out_of_benelux" + + if not errors: + name: str = api_data["cityName"] + country: str = api_data["country"] + unique_id: str = f"{name.lower()} {country.lower()}" + await self.async_set_unique_id(unique_id) + self._abort_if_unique_id_configured() + user_input[CONF_UNIQUE_ID] = unique_id + + return self.async_create_entry(title=name, data=user_input) + + default_location = user_input[CONF_LOCATION] + return self.async_show_form( + step_id="user", + data_schema=vol.Schema( + { + vol.Required( + CONF_LOCATION, default=default_location + ): LocationSelector() + } + ), + errors=errors, + ) + + +class IrmKmiOptionFlow(OptionsFlowWithReload): + """Option flow for the IRM KMI integration, help change the options once the integration was configured.""" + + async def async_step_init(self, user_input: dict | None = None) -> ConfigFlowResult: + """Manage the options.""" + if user_input is not None: + _LOGGER.debug("Provided config user is: %s", user_input) + return self.async_create_entry(data=user_input) + + return self.async_show_form( + step_id="init", + data_schema=vol.Schema( + { + vol.Optional( + CONF_LANGUAGE_OVERRIDE, + default=self.config_entry.options.get( + CONF_LANGUAGE_OVERRIDE, "none" + ), + ): SelectSelector( + SelectSelectorConfig( + options=CONF_LANGUAGE_OVERRIDE_OPTIONS, + mode=SelectSelectorMode.DROPDOWN, + translation_key=CONF_LANGUAGE_OVERRIDE, + ) + ) + } + ), + ) diff --git a/homeassistant/components/irm_kmi/const.py b/homeassistant/components/irm_kmi/const.py new file mode 100644 index 00000000000..afffc0fd242 --- /dev/null +++ b/homeassistant/components/irm_kmi/const.py @@ -0,0 +1,102 @@ +"""Constants for the IRM KMI integration.""" + +from typing import Final + +from homeassistant.components.weather import ( + ATTR_CONDITION_CLEAR_NIGHT, + ATTR_CONDITION_CLOUDY, + ATTR_CONDITION_FOG, + ATTR_CONDITION_LIGHTNING_RAINY, + ATTR_CONDITION_PARTLYCLOUDY, + ATTR_CONDITION_POURING, + ATTR_CONDITION_RAINY, + ATTR_CONDITION_SNOWY, + ATTR_CONDITION_SNOWY_RAINY, + ATTR_CONDITION_SUNNY, +) +from homeassistant.const import Platform, __version__ + +DOMAIN: Final = "irm_kmi" +PLATFORMS: Final = [Platform.WEATHER] + +OUT_OF_BENELUX: Final = [ + "außerhalb der Benelux (Brussels)", + "Hors de Belgique (Bxl)", + "Outside the Benelux (Brussels)", + "Buiten de Benelux (Brussel)", +] +LANGS: Final = ["en", "fr", "nl", "de"] + +CONF_LANGUAGE_OVERRIDE: Final = "language_override" +CONF_LANGUAGE_OVERRIDE_OPTIONS: Final = ["none", "fr", "nl", "de", "en"] + +# Dict to map ('ww', 'dayNight') tuple from IRM KMI to HA conditions. +IRM_KMI_TO_HA_CONDITION_MAP: Final = { + (0, "d"): ATTR_CONDITION_SUNNY, + (0, "n"): ATTR_CONDITION_CLEAR_NIGHT, + (1, "d"): ATTR_CONDITION_SUNNY, + (1, "n"): ATTR_CONDITION_CLEAR_NIGHT, + (2, "d"): ATTR_CONDITION_LIGHTNING_RAINY, + (2, "n"): ATTR_CONDITION_LIGHTNING_RAINY, + (3, "d"): ATTR_CONDITION_PARTLYCLOUDY, + (3, "n"): ATTR_CONDITION_PARTLYCLOUDY, + (4, "d"): ATTR_CONDITION_POURING, + (4, "n"): ATTR_CONDITION_POURING, + (5, "d"): ATTR_CONDITION_LIGHTNING_RAINY, + (5, "n"): ATTR_CONDITION_LIGHTNING_RAINY, + (6, "d"): ATTR_CONDITION_POURING, + (6, "n"): ATTR_CONDITION_POURING, + (7, "d"): ATTR_CONDITION_LIGHTNING_RAINY, + (7, "n"): ATTR_CONDITION_LIGHTNING_RAINY, + (8, "d"): ATTR_CONDITION_SNOWY_RAINY, + (8, "n"): ATTR_CONDITION_SNOWY_RAINY, + (9, "d"): ATTR_CONDITION_SNOWY_RAINY, + (9, "n"): ATTR_CONDITION_SNOWY_RAINY, + (10, "d"): ATTR_CONDITION_LIGHTNING_RAINY, + (10, "n"): ATTR_CONDITION_LIGHTNING_RAINY, + (11, "d"): ATTR_CONDITION_SNOWY, + (11, "n"): ATTR_CONDITION_SNOWY, + (12, "d"): ATTR_CONDITION_SNOWY, + (12, "n"): ATTR_CONDITION_SNOWY, + (13, "d"): ATTR_CONDITION_LIGHTNING_RAINY, + (13, "n"): ATTR_CONDITION_LIGHTNING_RAINY, + (14, "d"): ATTR_CONDITION_CLOUDY, + (14, "n"): ATTR_CONDITION_CLOUDY, + (15, "d"): ATTR_CONDITION_CLOUDY, + (15, "n"): ATTR_CONDITION_CLOUDY, + (16, "d"): ATTR_CONDITION_POURING, + (16, "n"): ATTR_CONDITION_POURING, + (17, "d"): ATTR_CONDITION_LIGHTNING_RAINY, + (17, "n"): ATTR_CONDITION_LIGHTNING_RAINY, + (18, "d"): ATTR_CONDITION_RAINY, + (18, "n"): ATTR_CONDITION_RAINY, + (19, "d"): ATTR_CONDITION_POURING, + (19, "n"): ATTR_CONDITION_POURING, + (20, "d"): ATTR_CONDITION_SNOWY_RAINY, + (20, "n"): ATTR_CONDITION_SNOWY_RAINY, + (21, "d"): ATTR_CONDITION_RAINY, + (21, "n"): ATTR_CONDITION_RAINY, + (22, "d"): ATTR_CONDITION_SNOWY, + (22, "n"): ATTR_CONDITION_SNOWY, + (23, "d"): ATTR_CONDITION_SNOWY, + (23, "n"): ATTR_CONDITION_SNOWY, + (24, "d"): ATTR_CONDITION_FOG, + (24, "n"): ATTR_CONDITION_FOG, + (25, "d"): ATTR_CONDITION_FOG, + (25, "n"): ATTR_CONDITION_FOG, + (26, "d"): ATTR_CONDITION_FOG, + (26, "n"): ATTR_CONDITION_FOG, + (27, "d"): ATTR_CONDITION_FOG, + (27, "n"): ATTR_CONDITION_FOG, +} + +IRM_KMI_NAME: Final = { + "fr": "Institut Royal Météorologique de Belgique", + "nl": "Koninklijk Meteorologisch Instituut van België", + "de": "Königliche Meteorologische Institut von Belgien", + "en": "Royal Meteorological Institute of Belgium", +} + +USER_AGENT: Final = ( + f"https://www.home-assistant.io/integrations/irm_kmi (version {__version__})" +) diff --git a/homeassistant/components/irm_kmi/coordinator.py b/homeassistant/components/irm_kmi/coordinator.py new file mode 100644 index 00000000000..9ff6d735cdd --- /dev/null +++ b/homeassistant/components/irm_kmi/coordinator.py @@ -0,0 +1,95 @@ +"""DataUpdateCoordinator for the IRM KMI integration.""" + +from datetime import timedelta +import logging + +from irm_kmi_api import IrmKmiApiClientHa, IrmKmiApiError + +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE, CONF_LOCATION +from homeassistant.core import HomeAssistant +from homeassistant.helpers.update_coordinator import ( + TimestampDataUpdateCoordinator, + UpdateFailed, +) +from homeassistant.util import dt as dt_util +from homeassistant.util.dt import utcnow + +from .data import ProcessedCoordinatorData +from .utils import preferred_language + +_LOGGER = logging.getLogger(__name__) + +type IrmKmiConfigEntry = ConfigEntry[IrmKmiCoordinator] + + +class IrmKmiCoordinator(TimestampDataUpdateCoordinator[ProcessedCoordinatorData]): + """Coordinator to update data from IRM KMI.""" + + def __init__( + self, + hass: HomeAssistant, + entry: IrmKmiConfigEntry, + api_client: IrmKmiApiClientHa, + ) -> None: + """Initialize the coordinator.""" + super().__init__( + hass, + _LOGGER, + config_entry=entry, + name="IRM KMI weather", + update_interval=timedelta(minutes=7), + ) + self._api = api_client + self._location = entry.data[CONF_LOCATION] + + async def _async_update_data(self) -> ProcessedCoordinatorData: + """Fetch data from API endpoint. + + This is the place to pre-process the data to lookup tables so entities can quickly look up their data. + :return: ProcessedCoordinatorData + """ + + self._api.expire_cache() + + try: + await self._api.refresh_forecasts_coord( + { + "lat": self._location[ATTR_LATITUDE], + "long": self._location[ATTR_LONGITUDE], + } + ) + + except IrmKmiApiError as err: + if ( + self.last_update_success_time is not None + and self.update_interval is not None + and self.last_update_success_time - utcnow() + < timedelta(seconds=2.5 * self.update_interval.seconds) + ): + return self.data + + _LOGGER.warning( + "Could not connect to the API since %s", self.last_update_success_time + ) + raise UpdateFailed( + f"Error communicating with API for general forecast: {err}. " + f"Last success time is: {self.last_update_success_time}" + ) from err + + if not self.last_update_success: + _LOGGER.warning("Successfully reconnected to the API") + + return await self.process_api_data() + + async def process_api_data(self) -> ProcessedCoordinatorData: + """From the API data, create the object that will be used in the entities.""" + tz = await dt_util.async_get_time_zone("Europe/Brussels") + lang = preferred_language(self.hass, self.config_entry) + + return ProcessedCoordinatorData( + current_weather=self._api.get_current_weather(tz), + daily_forecast=self._api.get_daily_forecast(tz, lang), + hourly_forecast=self._api.get_hourly_forecast(tz), + country=self._api.get_country(), + ) diff --git a/homeassistant/components/irm_kmi/data.py b/homeassistant/components/irm_kmi/data.py new file mode 100644 index 00000000000..5a70b97f36f --- /dev/null +++ b/homeassistant/components/irm_kmi/data.py @@ -0,0 +1,17 @@ +"""Define data classes for the IRM KMI integration.""" + +from dataclasses import dataclass, field + +from irm_kmi_api import CurrentWeatherData, ExtendedForecast + +from homeassistant.components.weather import Forecast + + +@dataclass +class ProcessedCoordinatorData: + """Dataclass that will be exposed to the entities consuming data from an IrmKmiCoordinator.""" + + current_weather: CurrentWeatherData + country: str + hourly_forecast: list[Forecast] = field(default_factory=list) + daily_forecast: list[ExtendedForecast] = field(default_factory=list) diff --git a/homeassistant/components/irm_kmi/entity.py b/homeassistant/components/irm_kmi/entity.py new file mode 100644 index 00000000000..a35c04ac425 --- /dev/null +++ b/homeassistant/components/irm_kmi/entity.py @@ -0,0 +1,28 @@ +"""Base class shared among IRM KMI entities.""" + +from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from .const import DOMAIN, IRM_KMI_NAME +from .coordinator import IrmKmiConfigEntry, IrmKmiCoordinator +from .utils import preferred_language + + +class IrmKmiBaseEntity(CoordinatorEntity[IrmKmiCoordinator]): + """Base methods for IRM KMI entities.""" + + _attr_attribution = ( + "Weather data from the Royal Meteorological Institute of Belgium meteo.be" + ) + _attr_has_entity_name = True + + def __init__(self, entry: IrmKmiConfigEntry) -> None: + """Init base properties for IRM KMI entities.""" + coordinator = entry.runtime_data + super().__init__(coordinator) + + self._attr_device_info = DeviceInfo( + entry_type=DeviceEntryType.SERVICE, + identifiers={(DOMAIN, entry.entry_id)}, + manufacturer=IRM_KMI_NAME.get(preferred_language(self.hass, entry)), + ) diff --git a/homeassistant/components/irm_kmi/manifest.json b/homeassistant/components/irm_kmi/manifest.json new file mode 100644 index 00000000000..f79819f5e83 --- /dev/null +++ b/homeassistant/components/irm_kmi/manifest.json @@ -0,0 +1,13 @@ +{ + "domain": "irm_kmi", + "name": "IRM KMI Weather Belgium", + "codeowners": ["@jdejaegh"], + "config_flow": true, + "dependencies": ["zone"], + "documentation": "https://www.home-assistant.io/integrations/irm_kmi", + "integration_type": "service", + "iot_class": "cloud_polling", + "loggers": ["irm_kmi_api"], + "quality_scale": "bronze", + "requirements": ["irm-kmi-api==1.1.0"] +} diff --git a/homeassistant/components/irm_kmi/quality_scale.yaml b/homeassistant/components/irm_kmi/quality_scale.yaml new file mode 100644 index 00000000000..15e34719025 --- /dev/null +++ b/homeassistant/components/irm_kmi/quality_scale.yaml @@ -0,0 +1,86 @@ +rules: + # Bronze + action-setup: + status: exempt + comment: > + No service action implemented in this integration at the moment. + appropriate-polling: + status: done + comment: > + Polling interval is set to 7 minutes. + brands: done + common-modules: done + config-flow-test-coverage: done + config-flow: done + dependency-transparency: done + docs-actions: + status: exempt + comment: > + No service action implemented in this integration at the moment. + docs-high-level-description: done + docs-installation-instructions: done + docs-removal-instructions: done + entity-event-setup: done + entity-unique-id: done + has-entity-name: done + runtime-data: done + test-before-configure: done + test-before-setup: done + unique-config-entry: done + + # Silver + action-exceptions: + status: exempt + comment: > + No service action implemented in this integration at the moment. + config-entry-unloading: done + docs-configuration-parameters: done + docs-installation-parameters: done + entity-unavailable: done + integration-owner: done + log-when-unavailable: done + parallel-updates: done + reauthentication-flow: + status: exempt + comment: > + There is no authentication for this integration + test-coverage: todo + # Gold + devices: done + diagnostics: todo + discovery-update-info: + status: exempt + comment: > + The integration does not look for devices on the network. It uses an online API. + discovery: + status: exempt + comment: > + The integration does not look for devices on the network. It uses an online API. + docs-data-update: done + docs-examples: todo + docs-known-limitations: done + docs-supported-devices: + status: exempt + comment: > + This integration does not integrate physical devices. + docs-supported-functions: done + docs-troubleshooting: todo + docs-use-cases: done + dynamic-devices: done + entity-category: todo + entity-device-class: todo + entity-disabled-by-default: todo + entity-translations: todo + exception-translations: todo + icon-translations: todo + reconfiguration-flow: + status: exempt + comment: > + There is no configuration per se, just a zone to pick. + repair-issues: done + stale-devices: done + + # Platinum + async-dependency: done + inject-websession: done + strict-typing: todo diff --git a/homeassistant/components/irm_kmi/strings.json b/homeassistant/components/irm_kmi/strings.json new file mode 100644 index 00000000000..810b61fc276 --- /dev/null +++ b/homeassistant/components/irm_kmi/strings.json @@ -0,0 +1,50 @@ +{ + "title": "Royal Meteorological Institute of Belgium", + "common": { + "language_override_description": "Override the Home Assistant language for the textual weather forecast." + }, + "config": { + "abort": { + "already_configured": "[%key:common::config_flow::abort::already_configured_location%]", + "api_error": "[%key:common::config_flow::error::cannot_connect%]", + "unknown": "[%key:common::config_flow::error::unknown%]" + }, + "step": { + "user": { + "data": { + "location": "[%key:common::config_flow::data::location%]" + }, + "data_description": { + "location": "[%key:common::config_flow::data::location%]" + } + } + }, + "error": { + "out_of_benelux": "The location is outside of Benelux. Pick a location in Benelux." + } + }, + "selector": { + "language_override": { + "options": { + "none": "Follow Home Assistant server language", + "fr": "French", + "nl": "Dutch", + "de": "German", + "en": "English" + } + } + }, + "options": { + "step": { + "init": { + "title": "Options", + "data": { + "language_override": "[%key:common::config_flow::data::language%]" + }, + "data_description": { + "language_override": "[%key:component::irm_kmi::common::language_override_description%]" + } + } + } + } +} diff --git a/homeassistant/components/irm_kmi/utils.py b/homeassistant/components/irm_kmi/utils.py new file mode 100644 index 00000000000..b5f36297696 --- /dev/null +++ b/homeassistant/components/irm_kmi/utils.py @@ -0,0 +1,18 @@ +"""Helper functions for use with IRM KMI integration.""" + +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant + +from .const import CONF_LANGUAGE_OVERRIDE, LANGS + + +def preferred_language(hass: HomeAssistant, config_entry: ConfigEntry | None) -> str: + """Get the preferred language for the integration if it was overridden by the configuration.""" + + if ( + config_entry is None + or config_entry.options.get(CONF_LANGUAGE_OVERRIDE) == "none" + ): + return hass.config.language if hass.config.language in LANGS else "en" + + return config_entry.options.get(CONF_LANGUAGE_OVERRIDE, "en") diff --git a/homeassistant/components/irm_kmi/weather.py b/homeassistant/components/irm_kmi/weather.py new file mode 100644 index 00000000000..a0b4286a50c --- /dev/null +++ b/homeassistant/components/irm_kmi/weather.py @@ -0,0 +1,158 @@ +"""Support for IRM KMI weather.""" + +from irm_kmi_api import CurrentWeatherData + +from homeassistant.components.weather import ( + Forecast, + SingleCoordinatorWeatherEntity, + WeatherEntityFeature, +) +from homeassistant.const import ( + CONF_UNIQUE_ID, + UnitOfPrecipitationDepth, + UnitOfPressure, + UnitOfSpeed, + UnitOfTemperature, +) +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback + +from .coordinator import IrmKmiConfigEntry, IrmKmiCoordinator +from .entity import IrmKmiBaseEntity + + +async def async_setup_entry( + _hass: HomeAssistant, + entry: IrmKmiConfigEntry, + async_add_entities: AddConfigEntryEntitiesCallback, +) -> None: + """Set up the weather entry.""" + async_add_entities([IrmKmiWeather(entry)]) + + +# Coordinator is used to centralize the data updates +PARALLEL_UPDATES = 0 + + +class IrmKmiWeather( + IrmKmiBaseEntity, # WeatherEntity + SingleCoordinatorWeatherEntity[IrmKmiCoordinator], +): + """Weather entity for IRM KMI weather.""" + + _attr_name = None + _attr_supported_features = ( + WeatherEntityFeature.FORECAST_DAILY + | WeatherEntityFeature.FORECAST_TWICE_DAILY + | WeatherEntityFeature.FORECAST_HOURLY + ) + _attr_native_temperature_unit = UnitOfTemperature.CELSIUS + _attr_native_wind_speed_unit = UnitOfSpeed.KILOMETERS_PER_HOUR + _attr_native_precipitation_unit = UnitOfPrecipitationDepth.MILLIMETERS + _attr_native_pressure_unit = UnitOfPressure.HPA + + def __init__(self, entry: IrmKmiConfigEntry) -> None: + """Create a new instance of the weather entity from a configuration entry.""" + IrmKmiBaseEntity.__init__(self, entry) + SingleCoordinatorWeatherEntity.__init__(self, entry.runtime_data) + self._attr_unique_id = entry.data[CONF_UNIQUE_ID] + + @property + def available(self) -> bool: + """Return True if entity is available.""" + return super().available + + @property + def current_weather(self) -> CurrentWeatherData: + """Return the current weather.""" + return self.coordinator.data.current_weather + + @property + def condition(self) -> str | None: + """Return the current condition.""" + return self.current_weather.get("condition") + + @property + def native_temperature(self) -> float | None: + """Return the temperature in native units.""" + return self.current_weather.get("temperature") + + @property + def native_wind_speed(self) -> float | None: + """Return the wind speed in native units.""" + return self.current_weather.get("wind_speed") + + @property + def native_wind_gust_speed(self) -> float | None: + """Return the wind gust speed in native units.""" + return self.current_weather.get("wind_gust_speed") + + @property + def wind_bearing(self) -> float | str | None: + """Return the wind bearing.""" + return self.current_weather.get("wind_bearing") + + @property + def native_pressure(self) -> float | None: + """Return the pressure in native units.""" + return self.current_weather.get("pressure") + + @property + def uv_index(self) -> float | None: + """Return the UV index.""" + return self.current_weather.get("uv_index") + + def _async_forecast_twice_daily(self) -> list[Forecast] | None: + """Return the daily forecast in native units.""" + return self.coordinator.data.daily_forecast + + def _async_forecast_daily(self) -> list[Forecast] | None: + """Return the daily forecast in native units.""" + return self.daily_forecast() + + def _async_forecast_hourly(self) -> list[Forecast] | None: + """Return the hourly forecast in native units.""" + return self.coordinator.data.hourly_forecast + + def daily_forecast(self) -> list[Forecast] | None: + """Return the daily forecast in native units.""" + data: list[Forecast] = self.coordinator.data.daily_forecast + + # The data in daily_forecast might contain nighttime forecast. + # The following handle the lowest temperature attribute to be displayed correctly. + if ( + len(data) > 1 + and not data[0].get("is_daytime") + and data[1].get("native_templow") is None + ): + data[1]["native_templow"] = data[0].get("native_templow") + if ( + data[1]["native_templow"] is not None + and data[1]["native_temperature"] is not None + and data[1]["native_templow"] > data[1]["native_temperature"] + ): + (data[1]["native_templow"], data[1]["native_temperature"]) = ( + data[1]["native_temperature"], + data[1]["native_templow"], + ) + + if len(data) > 0 and not data[0].get("is_daytime"): + return data + + if ( + len(data) > 1 + and data[0].get("native_templow") is None + and not data[1].get("is_daytime") + ): + data[0]["native_templow"] = data[1].get("native_templow") + if ( + data[0]["native_templow"] is not None + and data[0]["native_temperature"] is not None + and data[0]["native_templow"] > data[0]["native_temperature"] + ): + (data[0]["native_templow"], data[0]["native_temperature"]) = ( + data[0]["native_temperature"], + data[0]["native_templow"], + ) + + return [f for f in data if f.get("is_daytime")] diff --git a/homeassistant/generated/config_flows.py b/homeassistant/generated/config_flows.py index 55209291531..a3b7aa63060 100644 --- a/homeassistant/generated/config_flows.py +++ b/homeassistant/generated/config_flows.py @@ -310,6 +310,7 @@ FLOWS = { "ipma", "ipp", "iqvia", + "irm_kmi", "iron_os", "iskra", "islamic_prayer_times", diff --git a/homeassistant/generated/integrations.json b/homeassistant/generated/integrations.json index 0591305fa08..1b72bed62b9 100644 --- a/homeassistant/generated/integrations.json +++ b/homeassistant/generated/integrations.json @@ -3118,6 +3118,11 @@ "config_flow": false, "iot_class": "cloud_polling" }, + "irm_kmi": { + "integration_type": "service", + "config_flow": true, + "iot_class": "cloud_polling" + }, "iron_os": { "name": "IronOS", "integration_type": "hub", @@ -7969,6 +7974,7 @@ "input_select", "input_text", "integration", + "irm_kmi", "islamic_prayer_times", "local_calendar", "local_ip", diff --git a/requirements_all.txt b/requirements_all.txt index 45285b21df0..dccd226ac18 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1278,6 +1278,9 @@ iottycloud==0.3.0 # homeassistant.components.iperf3 iperf3==0.1.11 +# homeassistant.components.irm_kmi +irm-kmi-api==1.1.0 + # homeassistant.components.isal isal==1.8.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 2ca7601da1f..be4803bd890 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1109,6 +1109,9 @@ iometer==0.1.0 # homeassistant.components.iotty iottycloud==0.3.0 +# homeassistant.components.irm_kmi +irm-kmi-api==1.1.0 + # homeassistant.components.isal isal==1.8.0 diff --git a/tests/components/irm_kmi/__init__.py b/tests/components/irm_kmi/__init__.py new file mode 100644 index 00000000000..629c80d5d9e --- /dev/null +++ b/tests/components/irm_kmi/__init__.py @@ -0,0 +1 @@ +"""Tests of IRM KMI integration.""" diff --git a/tests/components/irm_kmi/conftest.py b/tests/components/irm_kmi/conftest.py new file mode 100644 index 00000000000..b3ef4fa1b89 --- /dev/null +++ b/tests/components/irm_kmi/conftest.py @@ -0,0 +1,123 @@ +"""Fixtures for the IRM KMI integration tests.""" + +from collections.abc import Generator +import json +from unittest.mock import MagicMock, patch + +from irm_kmi_api import IrmKmiApiError +import pytest + +from homeassistant.components.irm_kmi.const import DOMAIN +from homeassistant.const import ( + ATTR_LATITUDE, + ATTR_LONGITUDE, + CONF_LOCATION, + CONF_UNIQUE_ID, +) + +from tests.common import MockConfigEntry, load_fixture + + +@pytest.fixture +def mock_config_entry() -> MockConfigEntry: + """Return the default mocked config entry.""" + return MockConfigEntry( + title="Home", + domain=DOMAIN, + data={ + CONF_LOCATION: {ATTR_LATITUDE: 50.84, ATTR_LONGITUDE: 4.35}, + CONF_UNIQUE_ID: "city country", + }, + unique_id="50.84-4.35", + ) + + +@pytest.fixture +def mock_setup_entry() -> Generator[None]: + """Mock setting up a config entry.""" + with patch("homeassistant.components.irm_kmi.async_setup_entry", return_value=True): + yield + + +@pytest.fixture +def mock_get_forecast_in_benelux(): + """Mock a call to IrmKmiApiClient.get_forecasts_coord() so that it returns something valid and in the Benelux.""" + with patch( + "homeassistant.components.irm_kmi.config_flow.IrmKmiApiClient.get_forecasts_coord", + return_value={"cityName": "Brussels", "country": "BE"}, + ): + yield + + +@pytest.fixture +def mock_get_forecast_out_benelux_then_in_belgium(): + """Mock a call to IrmKmiApiClient.get_forecasts_coord() so that it returns something outside Benelux.""" + with patch( + "homeassistant.components.irm_kmi.config_flow.IrmKmiApiClient.get_forecasts_coord", + side_effect=[ + {"cityName": "Outside the Benelux (Brussels)", "country": "BE"}, + {"cityName": "Brussels", "country": "BE"}, + ], + ): + yield + + +@pytest.fixture +def mock_get_forecast_api_error(): + """Mock a call to IrmKmiApiClient.get_forecasts_coord() so that it raises an error.""" + with patch( + "homeassistant.components.irm_kmi.config_flow.IrmKmiApiClient.get_forecasts_coord", + side_effect=IrmKmiApiError, + ): + yield + + +@pytest.fixture +def mock_irm_kmi_api(request: pytest.FixtureRequest) -> Generator[None, MagicMock]: + """Return a mocked IrmKmi api client.""" + fixture: str = "forecast.json" + + forecast = json.loads(load_fixture(fixture, "irm_kmi")) + with patch( + "homeassistant.components.irm_kmi.IrmKmiApiClientHa", autospec=True + ) as irm_kmi_api_mock: + irm_kmi = irm_kmi_api_mock.return_value + irm_kmi.get_forecasts_coord.return_value = forecast + yield irm_kmi + + +@pytest.fixture +def mock_irm_kmi_api_nl(): + """Mock a call to IrmKmiApiClientHa.get_forecasts_coord() to return a forecast in The Netherlands.""" + fixture: str = "forecast_nl.json" + forecast = json.loads(load_fixture(fixture, "irm_kmi")) + with patch( + "homeassistant.components.irm_kmi.coordinator.IrmKmiApiClientHa.get_forecasts_coord", + return_value=forecast, + ): + yield + + +@pytest.fixture +def mock_irm_kmi_api_high_low_temp(): + """Mock a call to IrmKmiApiClientHa.get_forecasts_coord() to return high_low_temp.json forecast.""" + fixture: str = "high_low_temp.json" + forecast = json.loads(load_fixture(fixture, "irm_kmi")) + with patch( + "homeassistant.components.irm_kmi.coordinator.IrmKmiApiClientHa.get_forecasts_coord", + return_value=forecast, + ): + yield + + +@pytest.fixture +def mock_exception_irm_kmi_api( + request: pytest.FixtureRequest, +) -> Generator[None, MagicMock]: + """Return a mocked IrmKmi api client that will raise an error upon refreshing data.""" + with patch( + "homeassistant.components.irm_kmi.IrmKmiApiClientHa", autospec=True + ) as irm_kmi_api_mock: + irm_kmi = irm_kmi_api_mock.return_value + irm_kmi.refresh_forecasts_coord.side_effect = IrmKmiApiError + yield irm_kmi diff --git a/tests/components/irm_kmi/fixtures/forecast.json b/tests/components/irm_kmi/fixtures/forecast.json new file mode 100644 index 00000000000..06b8f3d81d7 --- /dev/null +++ b/tests/components/irm_kmi/fixtures/forecast.json @@ -0,0 +1,1474 @@ +{ + "cityName": "Namur", + "country": "BE", + "obs": { + "temp": 7, + "timestamp": "2023-12-26T18:30:00+01:00", + "ww": 15, + "dayNight": "n" + }, + "for": { + "daily": [ + { + "dayName": { + "fr": "Cette nuit", + "nl": "Vannacht", + "en": "Tonight", + "de": "heute abend" + }, + "period": "2", + "day_night": "0", + "dayNight": "n", + "text": { + "nl": "Vanavond verloopt droog, maar geleidelijk neemt ook de middelhoge bewolking toe. Vannacht verschijnen er alsmaar meer lage wolkenvelden. Vooral in de Ardennen kan er wat nevel en mist gevormd worden, waardoor het zicht bij momenten slecht is. Na middernacht begint het licht te regenen vanaf de Franse grens. De minima worden vroeg bereikt en liggen rond 0 of +1 graad op de hoogste toppen en tussen 3 en 6 graden in de meeste andere streken. De zwakke wind uit zuidwest krimpt naar het zuiden tot zuidoosten en wordt aan het einde van de nacht overal matig.", + "fr": "Ce soir, le temps restera sec même si des nuages moyens gagneront également notre territoire. Cette nuit, le ciel finira par se couvrir avec l'arrivée de nuages de plus basse altitude. Principalement en Ardenne, un peu de brume et de brouillard pourra se former, ce qui réduira parfois la visibilité. Après minuit, de faibles pluies se produiront depuis la frontière française. Les minima, atteints rapidement, se situeront autour de 0 ou +1 degré sur le relief et entre +3 et +6 degrés ailleurs. Le vent sera faible de secteur sud-ouest et deviendra le plus souvent modéré en fin de nuit." + }, + "dawnRiseSeconds": "31440", + "dawnSetSeconds": "60120", + "tempMin": 4, + "tempMax": null, + "ww1": 14, + "ww2": 19, + "wwevol": 0, + "ff1": 2, + "ff2": 3, + "ffevol": 0, + "dd": 0, + "ddText": { + "fr": "S", + "nl": "Z", + "en": "S", + "de": "S" + }, + "wind": { + "speed": 6, + "peakSpeed": null, + "dir": 0, + "dirText": { + "fr": "S", + "nl": "Z", + "en": "S", + "de": "S" + } + }, + "precipChance": 95, + "precipQuantity": "2" + }, + { + "dayName": { + "fr": "Mercredi", + "nl": "Woensdag", + "en": "Wednesday", + "de": "Mittwoch" + }, + "period": "3", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Foo", + "fr": "Bar", + "en": "Hey!" + }, + "dawnRiseSeconds": "31440", + "dawnSetSeconds": "60180", + "tempMin": 4, + "tempMax": 9, + "ww1": 3, + "ww2": null, + "wwevol": null, + "ff1": 4, + "ff2": null, + "ffevol": null, + "dd": 0, + "ddText": { + "fr": "S", + "nl": "Z", + "en": "S", + "de": "S" + }, + "wind": { + "speed": 20, + "peakSpeed": "50", + "dir": 0, + "dirText": { + "fr": "S", + "nl": "Z", + "en": "S", + "de": "S" + } + }, + "precipChance": 0, + "precipQuantity": "0" + }, + { + "dayName": { + "fr": "Jeudi", + "nl": "Donderdag", + "en": "Thursday", + "de": "Donnerstag" + }, + "period": "5", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Donderdag wisselen opklaringen en wolken elkaar af, waaruit plaatselijk enkele buien vallen. Aan het begin van de dag hangt er in de Ardennen veel bewolking met wat laatste lichte regen. Aan het einde van de dag bereiken iets meer buien de kuststreek, om nadien tijdens de daaropvolgende nacht op te schuiven naar het binnenland. Het is vrij winderig en zeer zacht met maxima van 7 graden in de Hoge Ardennen tot 11 graden over het westen van het land. De zuidwestenwind is matig tot vrij krachtig en aan zee soms krachtig met windstoten tot 60 of 70 km/h.", + "fr": "Jeudi, nuages et éclaircies se partageront le ciel avec quelques averses isolées. En début de journée, les nuages pourraient encore s'accrocher sur l'Ardenne avec quelques faibles pluies résiduelles. En fin de journée, des averses un peu plus nombreuses devraient aborder la région littorale, puis traverser notre pays au cours de la nuit suivante. Le temps sera assez venteux et très doux avec des maxima de 7 degrés en haute Ardenne à 11 degrés sur l'ouest du pays. Le vent de sud-ouest sera modéré à assez fort, le long du littoral parfois fort. Les rafales pourront atteindre 60 à 70 km/h." + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60180", + "tempMin": 7, + "tempMax": 10, + "ww1": 3, + "ww2": null, + "wwevol": null, + "ff1": 5, + "ff2": 4, + "ffevol": 1, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 29, + "peakSpeed": "60", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 0, + "precipQuantity": "0" + }, + { + "dayName": { + "fr": "Vendredi", + "nl": "Vrijdag", + "en": "Friday", + "de": "Freitag" + }, + "period": "7", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Vrijdag is het zacht en winderig. Bij momenten vallen er intense regenbuien. De maxima klimmen naar waarden tussen 6 en 10 graden bij een vrij krachtige en aan zee soms krachtige zuidwestenwind. Rukwinden zijn mogelijk tot 60 of 70 km/h.", + "fr": "Vendredi, le temps sera doux et venteux. De nouvelles pluies parfois importantes et sous forme d'averses traverseront notre pays. Les maxima varieront entre 6 et 10 degrés avec un vent assez fort de sud-ouest, le long du littoral parfois fort. Les rafales atteindront 60 à 70 km/h." + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60240", + "tempMin": 8, + "tempMax": 9, + "ww1": 6, + "ww2": 19, + "wwevol": 0, + "ff1": 5, + "ff2": null, + "ffevol": null, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 29, + "peakSpeed": "65", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 100, + "precipQuantity": "8" + }, + { + "dayName": { + "fr": "Samedi", + "nl": "Zaterdag", + "en": "Saturday", + "de": "Samstag" + }, + "period": "9", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Zaterdag wordt het onstabieler. We krijgen bewolkte perioden te verwerken, die soms plaats maken voor enkele zonnige momenten. Het wordt droger, maar toch blijven enkele buien nog steeds mogelijk. De maxima liggen tussen 5 en 9 graden. De westen- tot zuidwestenwind neemt tijdelijk af in kracht, maar blijft in de kustregio vrij krachtig waaien.", + "fr": "Samedi, nous passerons sous un régime plus variable où les passages nuageux laisseront par moments entrevoir quelques rayons de soleil. Il fera plus sec mais quelques averses resteront encore possibles. Les maxima varieront entre 5 et 9 degrés. Le vent d'ouest à sud-ouest diminuera temporairement mais restera encore assez soutenu le long du littoral." + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60300", + "tempMin": 4, + "tempMax": 8, + "ww1": 1, + "ww2": 15, + "wwevol": 0, + "ff1": 4, + "ff2": 5, + "ffevol": 0, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 20, + "peakSpeed": "55", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 50, + "precipQuantity": "0" + }, + { + "dayName": { + "fr": "Dimanche", + "nl": "Zondag", + "en": "Sunday", + "de": "Sonntag" + }, + "period": "11", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Zondag trekt een nieuwe actieve regenzone over ons land. Deze wordt aangedreven door een krachtige zuidwestenwind. Na zijn doortocht draait de wind naar het noordwesten en wordt het frisser en onstabieler met buien. We halen maxima van 6 tot 10 graden.", + "fr": "Dimanche, une nouvelle zone de pluie active traversera notre pays, poussée par un vigoureux vent de sud-ouest. Après son passage, le vent basculera au nord-ouest et de l'air plus frais et plus instable accompagné d'averses envahira notre pays. Les maxima varieront entre 6 et 10 degrés." + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60360", + "tempMin": 8, + "tempMax": 8, + "ww1": 19, + "ww2": null, + "wwevol": null, + "ff1": 6, + "ff2": 5, + "ffevol": 0, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 29, + "peakSpeed": "85", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 100, + "precipQuantity": "9" + }, + { + "dayName": { + "fr": "Lundi", + "nl": "Maandag", + "en": "Monday", + "de": "Montag" + }, + "period": "13", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Op Nieuwjaarsdag lijkt het rustiger te worden met minder regen en minder wind. Het wordt iets frisser met maxima tussen 3 en 7 graden.", + "fr": "Le jour de l'an devrait connaître une accalmie passagère avec moins de pluie et de vent. Il fera un peu plus frais avec des maxima de 3 à 7 degrés." + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60420", + "tempMin": 5, + "tempMax": 6, + "ww1": 18, + "ww2": 19, + "wwevol": 0, + "ff1": 1, + "ff2": 3, + "ffevol": 0, + "dd": 315, + "ddText": { + "fr": "SE", + "nl": "ZO", + "en": "SE", + "de": "SO" + }, + "wind": { + "speed": 12, + "peakSpeed": null, + "dir": 315, + "dirText": { + "fr": "SE", + "nl": "ZO", + "en": "SE", + "de": "SO" + } + }, + "precipChance": 80, + "precipQuantity": "3" + }, + { + "dayName": { + "fr": "Mardi", + "nl": "Dinsdag", + "en": "Tuesday", + "de": "Dienstag" + }, + "period": "15", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Volgende week dinsdag trekt een nieuwe regenzone over ons land. De maxima liggen tussen 5 en 9 graden.", + "fr": "Mardi prochain, une nouvelle zone de pluie devrait traverser notre pays. Les maxima varieront entre 5 et 9 degrés." + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60480", + "tempMin": 5, + "tempMax": 9, + "ww1": 19, + "ww2": null, + "wwevol": null, + "ff1": 5, + "ff2": null, + "ffevol": null, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 29, + "peakSpeed": "75", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 100, + "precipQuantity": "7" + } + ], + "showWarningTab": false, + "graph": { + "svg": [ + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tx&l=nl&k=782832cc606de3bad9b7f2002de4b4b1", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tx&l=fr&k=782832cc606de3bad9b7f2002de4b4b1", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tx&l=en&k=782832cc606de3bad9b7f2002de4b4b1", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tx&l=de&k=782832cc606de3bad9b7f2002de4b4b1" + }, + "ratio": 1.3638709677419354 + }, + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tn&l=nl&k=782832cc606de3bad9b7f2002de4b4b1", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tn&l=fr&k=782832cc606de3bad9b7f2002de4b4b1", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tn&l=en&k=782832cc606de3bad9b7f2002de4b4b1", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tn&l=de&k=782832cc606de3bad9b7f2002de4b4b1" + }, + "ratio": 1.3638709677419354 + }, + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=rr&l=nl&k=782832cc606de3bad9b7f2002de4b4b1", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=rr&l=fr&k=782832cc606de3bad9b7f2002de4b4b1", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=rr&l=en&k=782832cc606de3bad9b7f2002de4b4b1", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=rr&l=de&k=782832cc606de3bad9b7f2002de4b4b1" + }, + "ratio": 1.3638709677419354 + } + ] + }, + "hourly": [ + { + "hour": "18", + "temp": 7, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1020, + "windSpeedKm": 5, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "19", + "temp": 6, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1021, + "windSpeedKm": 5, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "20", + "temp": 5, + "ww": "14", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1021, + "windSpeedKm": 5, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "21", + "temp": 4, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1021, + "windSpeedKm": 5, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "22", + "temp": 4, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0.01, + "pressure": 1021, + "windSpeedKm": 5, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "23", + "temp": 5, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1021, + "windSpeedKm": 10, + "windPeakSpeedKm": null, + "windDirection": 338, + "windDirectionText": { + "nl": "ZZO", + "fr": "SSE", + "en": "SSE", + "de": "SSO" + }, + "dayNight": "n" + }, + { + "hour": "00", + "temp": 7, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1021, + "windSpeedKm": 10, + "windPeakSpeedKm": null, + "windDirection": 338, + "windDirectionText": { + "nl": "ZZO", + "fr": "SSE", + "en": "SSE", + "de": "SSO" + }, + "dayNight": "n", + "dateShow": "27/12", + "dateShowLocalized": { + "nl": "Woe.", + "fr": "Mer.", + "en": "Wed.", + "de": "Mit." + } + }, + { + "hour": "01", + "temp": 8, + "ww": "15", + "precipChance": "30", + "precipQuantity": 0.01, + "pressure": 1020, + "windSpeedKm": 15, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "02", + "temp": 8, + "ww": "18", + "precipChance": "70", + "precipQuantity": 0.98, + "pressure": 1020, + "windSpeedKm": 15, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "03", + "temp": 8, + "ww": "18", + "precipChance": "90", + "precipQuantity": 1.14, + "pressure": 1019, + "windSpeedKm": 15, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "04", + "temp": 9, + "ww": "18", + "precipChance": "70", + "precipQuantity": 0.15, + "pressure": 1019, + "windSpeedKm": 15, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "05", + "temp": 9, + "ww": "15", + "precipChance": "30", + "precipQuantity": 0, + "pressure": 1018, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "06", + "temp": 9, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0.01, + "pressure": 1018, + "windSpeedKm": 15, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "07", + "temp": 9, + "ww": "14", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1018, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "08", + "temp": 8, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1017, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "09", + "temp": 7, + "ww": "14", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1017, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "10", + "temp": 7, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1017, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "11", + "temp": 7, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1017, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "12", + "temp": 8, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1016, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "13", + "temp": 8, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1015, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "14", + "temp": 8, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1014, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "15", + "temp": 8, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "16", + "temp": 8, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 25, + "windPeakSpeedKm": 50, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "17", + "temp": 7, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "18", + "temp": 7, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "19", + "temp": 8, + "ww": "3", + "precipChance": "20", + "precipQuantity": 0, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "20", + "temp": 8, + "ww": "3", + "precipChance": "40", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 35, + "windPeakSpeedKm": 55, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "21", + "temp": 8, + "ww": "6", + "precipChance": "40", + "precipQuantity": 0.11, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "22", + "temp": 8, + "ww": "18", + "precipChance": "40", + "precipQuantity": 0.21, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "23", + "temp": 8, + "ww": "15", + "precipChance": "40", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "00", + "temp": 8, + "ww": "15", + "precipChance": "20", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n", + "dateShow": "28/12", + "dateShowLocalized": { + "nl": "Don.", + "fr": "Jeu.", + "en": "Thu.", + "de": "Don." + } + }, + { + "hour": "01", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "02", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "03", + "temp": 8, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "04", + "temp": 8, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1014, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "05", + "temp": 8, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "06", + "temp": 7, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1014, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "07", + "temp": 7, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1014, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "08", + "temp": 7, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1014, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "09", + "temp": 7, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0.01, + "pressure": 1014, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "10", + "temp": 8, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0.01, + "pressure": 1014, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "11", + "temp": 8, + "ww": "14", + "precipChance": "0", + "precipQuantity": 0.02, + "pressure": 1014, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "12", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1014, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "13", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 35, + "windPeakSpeedKm": 60, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "14", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0.01, + "pressure": 1013, + "windSpeedKm": 30, + "windPeakSpeedKm": 60, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "15", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "16", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "17", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "18", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + } + ], + "warning": [] + }, + "module": [ + { + "type": "svg", + "data": { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=pollen&l=nl&k=782832cc606de3bad9b7f2002de4b4b1", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=pollen&l=fr&k=782832cc606de3bad9b7f2002de4b4b1", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=pollen&l=en&k=782832cc606de3bad9b7f2002de4b4b1", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=pollen&l=de&k=782832cc606de3bad9b7f2002de4b4b1" + }, + "ratio": 3.0458333333333334 + } + }, + { + "type": "uv", + "data": { + "levelValue": 0.7, + "level": { + "nl": "Laag", + "fr": "Faible", + "en": "Low", + "de": "Niedrig" + }, + "title": { + "nl": "Uv-index", + "fr": "Indice UV", + "en": "UV Index", + "de": "UV Index" + } + } + }, + { + "type": "observation", + "data": { + "count": 690, + "title": { + "nl": "Waarnemingen vandaag", + "fr": "Observations d'aujourd'hui", + "en": "Today's Observations", + "de": "Beobachtungen heute" + } + } + }, + { + "type": "svg", + "data": { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=nl&k=782832cc606de3bad9b7f2002de4b4b1", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=fr&k=782832cc606de3bad9b7f2002de4b4b1", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=en&k=782832cc606de3bad9b7f2002de4b4b1", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=de&k=782832cc606de3bad9b7f2002de4b4b1" + }, + "ratio": 1.6587926509186353 + } + } + ], + "animation": { + "localisationLayer": "https://app.meteo.be/services/appv4/?s=getLocalizationLayerBE&ins=92094&f=2&k=2c886c51e74b671c8fc3865f4a0e9318", + "localisationLayerRatioX": 0.6667, + "localisationLayerRatioY": 0.523, + "speed": 0.3, + "type": "10min", + "unit": { + "fr": "mm/10min", + "nl": "mm/10min", + "en": "mm/10min", + "de": "mm/10min" + }, + "country": "BE", + "sequence": [ + { + "time": "2023-12-26T17:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261610&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T17:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261620&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T17:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261630&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T17:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261640&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T17:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261650&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 0.1, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T17:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261700&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 0.01, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T18:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261710&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 0.12, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T18:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261720&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 1.2, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T18:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261730&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 2, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T18:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261740&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-26T18:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312261750&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + } + ], + "threshold": [], + "sequenceHint": { + "nl": "Geen regen voorzien op korte termijn", + "fr": "Pas de pluie prévue prochainement", + "en": "No rain forecasted shortly", + "de": "Kein Regen erwartet in naher Zukunft" + } + }, + "todayObsCount": 690 +} diff --git a/tests/components/irm_kmi/fixtures/forecast_nl.json b/tests/components/irm_kmi/fixtures/forecast_nl.json new file mode 100644 index 00000000000..452ba581cc0 --- /dev/null +++ b/tests/components/irm_kmi/fixtures/forecast_nl.json @@ -0,0 +1,1355 @@ +{ + "cityName": "Lelystad", + "country": "NL", + "obs": { + "ww": 15, + "municipality_code": "0995", + "temp": 11, + "windSpeedKm": 40, + "timestamp": "2023-12-28T14:30:00+00:00", + "windDirection": 45, + "municipality": "Lelystad", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + }, + "dayNight": "d" + }, + "for": { + "daily": [ + { + "dayName": { + "nl": "Vandaag", + "fr": "Aujourd'hui", + "de": "Heute", + "en": "Today" + }, + "timestamp": "2023-12-28T12:00:00+00:00", + "text": { + "nl": "Waarschuwingen \nVanavond zijn er in het noordwesten zware windstoten mogelijk van 75-90 km/uur (code geel).\n\nVanochtend is het half bewolkt met in het noorden kans op een bui. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, af en toe even stormachtig, windkracht 8. Aan de kust komen windstoten voor van ongeveer 80 km/uur.\nVanmiddag is het half tot zwaar bewolkt met kans op een bui, vooral in het noorden en westen. De middagtemperatuur ligt rond 11°C. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, vooral later ook af en toe stormachtig, windkracht 8. Aan de kust zijn er windstoten tot ongeveer 80 km/uur.\nVanavond zijn er buien, alleen in het zuidoosten is het overwegend droog. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust hard tot stormachtig, windkracht 7 tot 8. Vooral in het noordwesten zijn windstoten mogelijk van 75-90 km/uur.\n\nKomende nacht komen er enkele buien voor. Met een minimumtemperatuur van ongeveer 8°C is het zacht. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met zware windstoten tot ongeveer 80 km/uur.\n\nMorgenochtend is het half tot zwaar bewolkt en zijn er enkele buien. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig hard, windkracht 6-7, met vooral in het noordwesten mogelijk zware windstoten tot ongeveer 80 km/uur.\nMorgenmiddag is er af en toe ruimte voor de zon en blijft het op de meeste plaatsen droog, alleen in het zuidoosten kan een enkele bui vallen. Met middagtemperaturen van ongeveer 10°C blijft het zacht. De wind uit het zuidwesten is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met in het Waddengebied zware windstoten tot ongeveer 80 km/uur.\nMorgenavond is het half tot zwaar bewolkt met een enkele bui. De wind komt uit het zuidwesten en is meest matig, aan de kust krachtig tot hard, windkracht 6-7, boven de Wadden eerst stormachtig, windkracht 8. \n(Bron: KNMI, 2023-12-28T06:56:00+01:00)\n", + "en": "Waarschuwingen \nVanavond zijn er in het noordwesten zware windstoten mogelijk van 75-90 km/uur (code geel).\n\nVanochtend is het half bewolkt met in het noorden kans op een bui. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, af en toe even stormachtig, windkracht 8. Aan de kust komen windstoten voor van ongeveer 80 km/uur.\nVanmiddag is het half tot zwaar bewolkt met kans op een bui, vooral in het noorden en westen. De middagtemperatuur ligt rond 11°C. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, vooral later ook af en toe stormachtig, windkracht 8. Aan de kust zijn er windstoten tot ongeveer 80 km/uur.\nVanavond zijn er buien, alleen in het zuidoosten is het overwegend droog. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust hard tot stormachtig, windkracht 7 tot 8. Vooral in het noordwesten zijn windstoten mogelijk van 75-90 km/uur.\n\nKomende nacht komen er enkele buien voor. Met een minimumtemperatuur van ongeveer 8°C is het zacht. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met zware windstoten tot ongeveer 80 km/uur.\n\nMorgenochtend is het half tot zwaar bewolkt en zijn er enkele buien. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig hard, windkracht 6-7, met vooral in het noordwesten mogelijk zware windstoten tot ongeveer 80 km/uur.\nMorgenmiddag is er af en toe ruimte voor de zon en blijft het op de meeste plaatsen droog, alleen in het zuidoosten kan een enkele bui vallen. Met middagtemperaturen van ongeveer 10°C blijft het zacht. De wind uit het zuidwesten is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met in het Waddengebied zware windstoten tot ongeveer 80 km/uur.\nMorgenavond is het half tot zwaar bewolkt met een enkele bui. De wind komt uit het zuidwesten en is meest matig, aan de kust krachtig tot hard, windkracht 6-7, boven de Wadden eerst stormachtig, windkracht 8. \n(Bron: KNMI, 2023-12-28T06:56:00+01:00)\n", + "fr": "Waarschuwingen \nVanavond zijn er in het noordwesten zware windstoten mogelijk van 75-90 km/uur (code geel).\n\nVanochtend is het half bewolkt met in het noorden kans op een bui. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, af en toe even stormachtig, windkracht 8. Aan de kust komen windstoten voor van ongeveer 80 km/uur.\nVanmiddag is het half tot zwaar bewolkt met kans op een bui, vooral in het noorden en westen. De middagtemperatuur ligt rond 11°C. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, vooral later ook af en toe stormachtig, windkracht 8. Aan de kust zijn er windstoten tot ongeveer 80 km/uur.\nVanavond zijn er buien, alleen in het zuidoosten is het overwegend droog. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust hard tot stormachtig, windkracht 7 tot 8. Vooral in het noordwesten zijn windstoten mogelijk van 75-90 km/uur.\n\nKomende nacht komen er enkele buien voor. Met een minimumtemperatuur van ongeveer 8°C is het zacht. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met zware windstoten tot ongeveer 80 km/uur.\n\nMorgenochtend is het half tot zwaar bewolkt en zijn er enkele buien. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig hard, windkracht 6-7, met vooral in het noordwesten mogelijk zware windstoten tot ongeveer 80 km/uur.\nMorgenmiddag is er af en toe ruimte voor de zon en blijft het op de meeste plaatsen droog, alleen in het zuidoosten kan een enkele bui vallen. Met middagtemperaturen van ongeveer 10°C blijft het zacht. De wind uit het zuidwesten is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met in het Waddengebied zware windstoten tot ongeveer 80 km/uur.\nMorgenavond is het half tot zwaar bewolkt met een enkele bui. De wind komt uit het zuidwesten en is meest matig, aan de kust krachtig tot hard, windkracht 6-7, boven de Wadden eerst stormachtig, windkracht 8. \n(Bron: KNMI, 2023-12-28T06:56:00+01:00)\n", + "de": "Waarschuwingen \nVanavond zijn er in het noordwesten zware windstoten mogelijk van 75-90 km/uur (code geel).\n\nVanochtend is het half bewolkt met in het noorden kans op een bui. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, af en toe even stormachtig, windkracht 8. Aan de kust komen windstoten voor van ongeveer 80 km/uur.\nVanmiddag is het half tot zwaar bewolkt met kans op een bui, vooral in het noorden en westen. De middagtemperatuur ligt rond 11°C. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, vooral later ook af en toe stormachtig, windkracht 8. Aan de kust zijn er windstoten tot ongeveer 80 km/uur.\nVanavond zijn er buien, alleen in het zuidoosten is het overwegend droog. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust hard tot stormachtig, windkracht 7 tot 8. Vooral in het noordwesten zijn windstoten mogelijk van 75-90 km/uur.\n\nKomende nacht komen er enkele buien voor. Met een minimumtemperatuur van ongeveer 8°C is het zacht. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met zware windstoten tot ongeveer 80 km/uur.\n\nMorgenochtend is het half tot zwaar bewolkt en zijn er enkele buien. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig hard, windkracht 6-7, met vooral in het noordwesten mogelijk zware windstoten tot ongeveer 80 km/uur.\nMorgenmiddag is er af en toe ruimte voor de zon en blijft het op de meeste plaatsen droog, alleen in het zuidoosten kan een enkele bui vallen. Met middagtemperaturen van ongeveer 10°C blijft het zacht. De wind uit het zuidwesten is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met in het Waddengebied zware windstoten tot ongeveer 80 km/uur.\nMorgenavond is het half tot zwaar bewolkt met een enkele bui. De wind komt uit het zuidwesten en is meest matig, aan de kust krachtig tot hard, windkracht 6-7, boven de Wadden eerst stormachtig, windkracht 8. \n(Bron: KNMI, 2023-12-28T06:56:00+01:00)\n" + }, + "dayNight": "d", + "tempMin": null, + "tempMax": 11, + "ww1": 4, + "ww2": null, + "wwevol": null, + "ff1": 5, + "ff2": null, + "ffevol": null, + "windSpeedKm": 32, + "dd": 45, + "ddText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + }, + "wind": { + "speed": 32, + "peakSpeed": 33, + "dir": 45, + "dirText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + } + }, + "precipChance": null, + "precipQuantity": 0.1, + "uvIndex": 1, + "sunRiseUtc": 28063, + "sunSetUtc": 56046, + "sunRise": 31663, + "sunSet": 59646 + }, + { + "dayName": { + "nl": "Vannacht", + "fr": "Cette nuit", + "de": "Heute abend", + "en": "Tonight" + }, + "timestamp": "2023-12-29T00:00:00+00:00", + "dayNight": "n", + "tempMin": 9, + "tempMax": null, + "ww1": 15, + "ww2": null, + "wwevol": null, + "ff1": 5, + "ff2": null, + "ffevol": null, + "windSpeedKm": 31, + "dd": 45, + "ddText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + }, + "wind": { + "speed": 31, + "peakSpeed": 32, + "dir": 45, + "dirText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + } + }, + "precipChance": null, + "precipQuantity": 3, + "uvIndex": null, + "sunRiseUtc": null, + "sunSetUtc": null, + "sunRise": null, + "sunSet": null + }, + { + "dayName": { + "nl": "Morgen", + "fr": "Demain", + "de": "Morgen", + "en": "Tomorrow" + }, + "timestamp": "2023-12-29T12:00:00+00:00", + "dayNight": "d", + "tempMin": null, + "tempMax": 10, + "ww1": 3, + "ww2": null, + "wwevol": null, + "ff1": 5, + "ff2": null, + "ffevol": null, + "windSpeedKm": 26, + "dd": 68, + "ddText": { + "nl": "WZW", + "fr": "OSO", + "de": "WSW", + "en": "WSW" + }, + "wind": { + "speed": 26, + "peakSpeed": 28, + "dir": 68, + "dirText": { + "nl": "WZW", + "fr": "OSO", + "de": "WSW", + "en": "WSW" + } + }, + "precipChance": null, + "precipQuantity": 3.8, + "uvIndex": 1, + "sunRiseUtc": 28068, + "sunSetUtc": 56100, + "sunRise": 31668, + "sunSet": 59700 + }, + { + "dayName": { + "nl": "Zaterdag", + "fr": "Samedi", + "de": "Samstag", + "en": "Saturday" + }, + "timestamp": "2023-12-30T12:00:00+00:00", + "dayNight": "d", + "tempMin": 5, + "tempMax": 10, + "ww1": 16, + "ww2": null, + "wwevol": null, + "ff1": 4, + "ff2": null, + "ffevol": null, + "windSpeedKm": 22, + "dd": 45, + "ddText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + }, + "wind": { + "speed": 22, + "peakSpeed": 25, + "dir": 45, + "dirText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + } + }, + "precipChance": null, + "precipQuantity": 1.7, + "uvIndex": 1, + "sunRiseUtc": 28069, + "sunSetUtc": 56157, + "sunRise": 31669, + "sunSet": 59757 + }, + { + "dayName": { + "nl": "Zondag", + "fr": "Dimanche", + "de": "Sonntag", + "en": "Sunday" + }, + "timestamp": "2023-12-31T12:00:00+00:00", + "dayNight": "d", + "tempMin": 7, + "tempMax": 9, + "ww1": 19, + "ww2": null, + "wwevol": null, + "ff1": 5, + "ff2": null, + "ffevol": null, + "windSpeedKm": 30, + "dd": 23, + "ddText": { + "nl": "ZZW", + "fr": "SSO", + "de": "SSW", + "en": "SSW" + }, + "wind": { + "speed": 30, + "peakSpeed": 31, + "dir": 23, + "dirText": { + "nl": "ZZW", + "fr": "SSO", + "de": "SSW", + "en": "SSW" + } + }, + "precipChance": null, + "precipQuantity": 4.2, + "uvIndex": 1, + "sunRiseUtc": 28067, + "sunSetUtc": 56216, + "sunRise": 31667, + "sunSet": 59816 + }, + { + "dayName": { + "nl": "Maandag", + "fr": "Lundi", + "de": "Montag", + "en": "Monday" + }, + "timestamp": "2024-01-01T12:00:00+00:00", + "dayNight": "d", + "tempMin": 5, + "tempMax": 7, + "ww1": 16, + "ww2": null, + "wwevol": null, + "ff1": 4, + "ff2": null, + "ffevol": null, + "windSpeedKm": 23, + "dd": 45, + "ddText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + }, + "wind": { + "speed": 23, + "peakSpeed": 28, + "dir": 45, + "dirText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + } + }, + "precipChance": null, + "precipQuantity": 2.2, + "uvIndex": 1, + "sunRiseUtc": 28062, + "sunSetUtc": 56279, + "sunRise": 31662, + "sunSet": 59879 + }, + { + "dayName": { + "nl": "Dinsdag", + "fr": "Mardi", + "de": "Dienstag", + "en": "Tuesday" + }, + "timestamp": "2024-01-02T12:00:00+00:00", + "dayNight": "d", + "tempMin": 3, + "tempMax": 6, + "ww1": 16, + "ww2": null, + "wwevol": null, + "ff1": 3, + "ff2": null, + "ffevol": null, + "windSpeedKm": 15, + "dd": 45, + "ddText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + }, + "wind": { + "speed": 15, + "peakSpeed": 16, + "dir": 45, + "dirText": { + "nl": "ZW", + "fr": "SO", + "de": "SW", + "en": "SW" + } + }, + "precipChance": null, + "precipQuantity": 1.4, + "uvIndex": 1, + "sunRiseUtc": 28052, + "sunSetUtc": 56344, + "sunRise": 31652, + "sunSet": 59944 + }, + { + "dayName": { + "nl": "Woensdag", + "fr": "Mercredi", + "de": "Mittwoch", + "en": "Wednesday" + }, + "timestamp": "2024-01-03T12:00:00+00:00", + "dayNight": "d", + "tempMin": 3, + "tempMax": 6, + "ww1": 16, + "ww2": null, + "wwevol": null, + "ff1": 3, + "ff2": null, + "ffevol": null, + "windSpeedKm": 13, + "dd": 23, + "ddText": { + "nl": "ZZW", + "fr": "SSO", + "de": "SSW", + "en": "SSW" + }, + "wind": { + "speed": 13, + "peakSpeed": 14, + "dir": 23, + "dirText": { + "nl": "ZZW", + "fr": "SSO", + "de": "SSW", + "en": "SSW" + } + }, + "precipChance": null, + "precipQuantity": 1, + "uvIndex": 1, + "sunRiseUtc": 28040, + "sunSetUtc": 56412, + "sunRise": 31640, + "sunSet": 60012 + } + ], + "showWarningTab": false, + "graph": { + "svg": [ + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=tx&l=nl&k=353efbb53695c7207f520b00303e716a", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=tx&l=fr&k=353efbb53695c7207f520b00303e716a", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=tx&l=en&k=353efbb53695c7207f520b00303e716a", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=tx&l=de&k=353efbb53695c7207f520b00303e716a" + }, + "ratio": 1.3638709677419354 + }, + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=tn&l=nl&k=353efbb53695c7207f520b00303e716a", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=tn&l=fr&k=353efbb53695c7207f520b00303e716a", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=tn&l=en&k=353efbb53695c7207f520b00303e716a", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=tn&l=de&k=353efbb53695c7207f520b00303e716a" + }, + "ratio": 1.3638709677419354 + }, + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=rr&l=nl&k=353efbb53695c7207f520b00303e716a", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=rr&l=fr&k=353efbb53695c7207f520b00303e716a", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=rr&l=en&k=353efbb53695c7207f520b00303e716a", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=200995&e=rr&l=de&k=353efbb53695c7207f520b00303e716a" + }, + "ratio": 1.3638709677419354 + } + ] + }, + "hourly": [ + { + "hourUtc": "14", + "hour": "15", + "temp": 10, + "windSpeedKm": 33, + "dayNight": "d", + "ww": "15", + "pressure": "1008", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "15", + "hour": "16", + "temp": 10, + "windSpeedKm": 32, + "dayNight": "d", + "ww": "15", + "pressure": "1008", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "16", + "hour": "17", + "temp": 10, + "windSpeedKm": 32, + "dayNight": "n", + "ww": "15", + "pressure": "1007", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "17", + "hour": "18", + "temp": 10, + "windSpeedKm": 35, + "dayNight": "n", + "ww": "15", + "pressure": "1007", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "18", + "hour": "19", + "temp": 10, + "windSpeedKm": 35, + "dayNight": "n", + "ww": "15", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "19", + "hour": "20", + "temp": 10, + "windSpeedKm": 35, + "dayNight": "n", + "ww": "15", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "20", + "hour": "21", + "temp": 10, + "windSpeedKm": 35, + "dayNight": "n", + "ww": "15", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "21", + "hour": "22", + "temp": 10, + "windSpeedKm": 35, + "dayNight": "n", + "ww": "16", + "pressure": "1006", + "precipQuantity": 0.7, + "precipChance": "70", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "22", + "hour": "23", + "temp": 10, + "windSpeedKm": 37, + "dayNight": "n", + "ww": "16", + "pressure": "1006", + "precipQuantity": 0.1, + "precipChance": "10", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "23", + "hour": "00", + "temp": 10, + "dateShowLocalized": { + "fr": "Ven.", + "en": "Fri.", + "nl": "Vri.", + "de": "Fre." + }, + "windSpeedKm": 35, + "dayNight": "n", + "ww": "15", + "pressure": "1006", + "precipQuantity": 0, + "dateShow": "29/12", + "precipChance": "20", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "00", + "hour": "01", + "temp": 10, + "windSpeedKm": 31, + "dayNight": "n", + "ww": "16", + "pressure": "1005", + "precipQuantity": 1.9, + "precipChance": "80", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "01", + "hour": "02", + "temp": 10, + "windSpeedKm": 38, + "dayNight": "n", + "ww": "16", + "pressure": "1005", + "precipQuantity": 0.6, + "precipChance": "70", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "02", + "hour": "03", + "temp": 10, + "windSpeedKm": 35, + "dayNight": "n", + "ww": "3", + "pressure": "1005", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "03", + "hour": "04", + "temp": 10, + "windSpeedKm": 34, + "dayNight": "n", + "ww": "15", + "pressure": "1005", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "04", + "hour": "05", + "temp": 9, + "windSpeedKm": 35, + "dayNight": "n", + "ww": "3", + "pressure": "1005", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "05", + "hour": "06", + "temp": 9, + "windSpeedKm": 34, + "dayNight": "n", + "ww": "15", + "pressure": "1005", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "06", + "hour": "07", + "temp": 9, + "windSpeedKm": 32, + "dayNight": "n", + "ww": "3", + "pressure": "1005", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "07", + "hour": "08", + "temp": 9, + "windSpeedKm": 31, + "dayNight": "n", + "ww": "3", + "pressure": "1005", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "08", + "hour": "09", + "temp": 9, + "windSpeedKm": 31, + "dayNight": "d", + "ww": "3", + "pressure": "1005", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "09", + "hour": "10", + "temp": 9, + "windSpeedKm": 32, + "dayNight": "d", + "ww": "15", + "pressure": "1005", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "10", + "hour": "11", + "temp": 10, + "windSpeedKm": 32, + "dayNight": "d", + "ww": "3", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "11", + "hour": "12", + "temp": 10, + "windSpeedKm": 34, + "dayNight": "d", + "ww": "3", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "12", + "hour": "13", + "temp": 10, + "windSpeedKm": 33, + "dayNight": "d", + "ww": "3", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "13", + "hour": "14", + "temp": 10, + "windSpeedKm": 31, + "dayNight": "d", + "ww": "3", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "14", + "hour": "15", + "temp": 10, + "windSpeedKm": 28, + "dayNight": "d", + "ww": "0", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "15", + "hour": "16", + "temp": 9, + "windSpeedKm": 24, + "dayNight": "d", + "ww": "0", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "16", + "hour": "17", + "temp": 8, + "windSpeedKm": 20, + "dayNight": "n", + "ww": "0", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "17", + "hour": "18", + "temp": 8, + "windSpeedKm": 18, + "dayNight": "n", + "ww": "3", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + }, + { + "hourUtc": "18", + "hour": "19", + "temp": 8, + "windSpeedKm": 15, + "dayNight": "n", + "ww": "15", + "pressure": "1005", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "23", + "windDirectionText": { + "fr": "SSO", + "en": "SSW", + "nl": "ZZW", + "de": "SSW" + } + }, + { + "hourUtc": "19", + "hour": "20", + "temp": 8, + "windSpeedKm": 22, + "dayNight": "n", + "ww": "16", + "pressure": "1005", + "precipQuantity": 5.7, + "precipChance": "100", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "20", + "hour": "21", + "temp": 7, + "windSpeedKm": 26, + "dayNight": "n", + "ww": "6", + "pressure": "1006", + "precipQuantity": 3.8, + "precipChance": "100", + "windDirection": "90", + "windDirectionText": { + "fr": "O", + "en": "W", + "nl": "W", + "de": "W" + } + }, + { + "hourUtc": "21", + "hour": "22", + "temp": 8, + "windSpeedKm": 24, + "dayNight": "n", + "ww": "3", + "pressure": "1006", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "22", + "hour": "23", + "temp": 7, + "windSpeedKm": 22, + "dayNight": "n", + "ww": "15", + "pressure": "1007", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "23", + "hour": "00", + "temp": 8, + "dateShowLocalized": { + "fr": "Sam.", + "en": "Sat.", + "nl": "Zat.", + "de": "Sam." + }, + "windSpeedKm": 26, + "dayNight": "n", + "ww": "3", + "pressure": "1008", + "precipQuantity": 0, + "dateShow": "30/12", + "precipChance": "0", + "windDirection": "90", + "windDirectionText": { + "fr": "O", + "en": "W", + "nl": "W", + "de": "W" + } + }, + { + "hourUtc": "00", + "hour": "01", + "temp": 7, + "windSpeedKm": 26, + "dayNight": "n", + "ww": "0", + "pressure": "1007", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "90", + "windDirectionText": { + "fr": "O", + "en": "W", + "nl": "W", + "de": "W" + } + }, + { + "hourUtc": "01", + "hour": "02", + "temp": 7, + "windSpeedKm": 24, + "dayNight": "n", + "ww": "0", + "pressure": "1008", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "90", + "windDirectionText": { + "fr": "O", + "en": "W", + "nl": "W", + "de": "W" + } + }, + { + "hourUtc": "02", + "hour": "03", + "temp": 7, + "windSpeedKm": 24, + "dayNight": "n", + "ww": "3", + "pressure": "1008", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "90", + "windDirectionText": { + "fr": "O", + "en": "W", + "nl": "W", + "de": "W" + } + }, + { + "hourUtc": "03", + "hour": "04", + "temp": 7, + "windSpeedKm": 23, + "dayNight": "n", + "ww": "0", + "pressure": "1009", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "04", + "hour": "05", + "temp": 6, + "windSpeedKm": 23, + "dayNight": "n", + "ww": "0", + "pressure": "1009", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "05", + "hour": "06", + "temp": 6, + "windSpeedKm": 21, + "dayNight": "n", + "ww": "3", + "pressure": "1009", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "06", + "hour": "07", + "temp": 6, + "windSpeedKm": 20, + "dayNight": "n", + "ww": "3", + "pressure": "1010", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "07", + "hour": "08", + "temp": 6, + "windSpeedKm": 17, + "dayNight": "n", + "ww": "3", + "pressure": "1011", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "08", + "hour": "09", + "temp": 6, + "windSpeedKm": 13, + "dayNight": "d", + "ww": "0", + "pressure": "1011", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "68", + "windDirectionText": { + "fr": "OSO", + "en": "WSW", + "nl": "WZW", + "de": "WSW" + } + }, + { + "hourUtc": "09", + "hour": "10", + "temp": 5, + "windSpeedKm": 12, + "dayNight": "d", + "ww": "3", + "pressure": "1012", + "precipQuantity": 0, + "precipChance": "0", + "windDirection": "45", + "windDirectionText": { + "fr": "SO", + "en": "SW", + "nl": "ZW", + "de": "SW" + } + } + ], + "warning": [] + }, + "module": [ + { + "type": "uv", + "data": { + "levelValue": 1, + "level": { + "nl": "Laag", + "fr": "Faible", + "en": "Low", + "de": "Niedrig" + }, + "title": { + "nl": "Uv-index", + "fr": "Indice UV", + "en": "UV Index", + "de": "UV Index" + } + } + }, + { + "type": "observation", + "data": { + "count": 480, + "title": { + "nl": "Waarnemingen vandaag", + "fr": "Observations d'aujourd'hui", + "en": "Today's Observations", + "de": "Beobachtungen heute" + } + } + }, + { + "type": "svg", + "data": { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem_KNMI&l=nl&k=353efbb53695c7207f520b00303e716a", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem_KNMI&l=fr&k=353efbb53695c7207f520b00303e716a", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem_KNMI&l=en&k=353efbb53695c7207f520b00303e716a", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem_KNMI&l=de&k=353efbb53695c7207f520b00303e716a" + }, + "ratio": 1.6587926509186353 + } + } + ], + "animation": { + "localisationLayer": "https://app.meteo.be/services/appv4/?s=getLocalizationLayerNL&ins=200995&f=2&k=9145c16494963cfccf2854556ee8bf52", + "localisationLayerRatioX": 0.5716, + "localisationLayerRatioY": 0.3722, + "speed": 0.3, + "type": "5min", + "unit": { + "fr": "mm/h", + "nl": "mm/h", + "en": "mm/h", + "de": "mm/Std" + }, + "country": "NL", + "sequence": [ + { + "time": "2023-12-28T13:50:00+00:00", + "uri": "https://cdn.knmi.nl/knmi/map/page/weer/actueel-weer/neerslagradar/weerapp/RAD_NL25_PCP_CM_202312281350_640.png", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-28T13:55:00+00:00", + "uri": "https://cdn.knmi.nl/knmi/map/page/weer/actueel-weer/neerslagradar/weerapp/RAD_NL25_PCP_CM_202312281355_640.png", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-28T14:00:00+00:00", + "uri": "https://cdn.knmi.nl/knmi/map/page/weer/actueel-weer/neerslagradar/weerapp/RAD_NL25_PCP_CM_202312281400_640.png", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-28T14:05:00+00:00", + "uri": "https://cdn.knmi.nl/knmi/map/page/weer/actueel-weer/neerslagradar/weerapp/RAD_NL25_PCP_CM_202312281405_640.png", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-28T14:10:00+00:00", + "uri": "https://cdn.knmi.nl/knmi/map/page/weer/actueel-weer/neerslagradar/weerapp/RAD_NL25_PCP_CM_202312281410_640.png", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-28T14:15:00+00:00", + "uri": "https://cdn.knmi.nl/knmi/map/page/weer/actueel-weer/neerslagradar/weerapp/RAD_NL25_PCP_CM_202312281415_640.png", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-28T14:20:00+00:00", + "uri": "https://cdn.knmi.nl/knmi/map/page/weer/actueel-weer/neerslagradar/weerapp/RAD_NL25_PCP_CM_202312281420_640.png", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "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", + "value": 0.15, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + } + ], + "threshold": [], + "sequenceHint": { + "nl": "Geen regen voorzien op korte termijn", + "fr": "Pas de pluie prévue prochainement", + "en": "No rain forecasted shortly", + "de": "Kein Regen erwartet in naher Zukunft" + } + }, + "todayObsCount": 480 +} diff --git a/tests/components/irm_kmi/fixtures/forecast_out_of_benelux.json b/tests/components/irm_kmi/fixtures/forecast_out_of_benelux.json new file mode 100644 index 00000000000..a2b2a805e2c --- /dev/null +++ b/tests/components/irm_kmi/fixtures/forecast_out_of_benelux.json @@ -0,0 +1,1625 @@ +{ + "cityName": "Hors de Belgique (Bxl)", + "country": "BE", + "obs": { + "temp": 9, + "timestamp": "2023-12-27T11:20:00+01:00", + "ww": 15, + "dayNight": "d" + }, + "for": { + "daily": [ + { + "dayName": { + "fr": "Mercredi", + "nl": "Woensdag", + "en": "Wednesday", + "de": "Mittwoch" + }, + "period": "1", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Deze ochtend start de dag betrokken met lichte regen op de meeste plaatsen. In de voormiddag verlaat de zwakke regenzone ons land via Nederland. In de namiddag blijft het droog en wordt het vrij zonnig met soms wat meer hoge sluierwolken. De maxima liggen tussen 5 en 8 graden in het zuiden van het land en rond 9 of 10 graden in het centrum en aan zee. De matige zuidenwind ruimt naar zuidzuidwest en wordt vrij krachtig tot lokaal krachtig aan zee. Vooral in de kuststreek en op het Ardense reliëf zijn er windstoten mogelijk rond 50 km/h.", + "fr": "Ce matin, la journée débutera sous les nuages et de faibles pluies en de nombreux endroits. En matinée, cette zone de précipitations affaiblies quittera notre pays pour les Pays-Bas. L'après-midi, le temps restera sec et assez ensoleillé même si le soleil sera parfois masqué par des champs de nuages élevés. Les maxima seront compris entre 5 et 8 degrés dans le sud et proches de 9 ou 10 degrés en dans le centre et à la mer. Le vent modéré de sud virera au sud-sud-ouest et deviendra assez fort, à parfois fort au littoral. Des rafales de 50 km/h pourront se produire, essentiellement à la côte et sur les hauteurs de l'Ardenne." + }, + "dawnRiseSeconds": "31440", + "dawnSetSeconds": "60180", + "tempMin": null, + "tempMax": 10, + "ww1": 14, + "ww2": 3, + "wwevol": 0, + "ff1": 4, + "ff2": null, + "ffevol": null, + "dd": 22, + "ddText": { + "fr": "SSO", + "nl": "ZZW", + "en": "SSW", + "de": "SSW" + }, + "wind": { + "speed": 20, + "peakSpeed": null, + "dir": 22, + "dirText": { + "fr": "SSO", + "nl": "ZZW", + "en": "SSW", + "de": "SSW" + } + }, + "precipChance": 0, + "precipQuantity": "0" + }, + { + "dayName": { + "fr": "Cette nuit", + "nl": "Vannacht", + "en": "Tonight", + "de": "heute abend" + }, + "period": "2", + "day_night": "0", + "dayNight": "n", + "text": { + "nl": "Vanavond en vannacht trekt een volgende (zwakke) storing door het land van west naar oost met wat regen of enkele buien. Aan de achterzijde van deze storing klaart het uit. Tegen het einde van de nacht verlaat de regezone stilaan ons land via het zuidoosten. De minima liggen tussen 4 en 9 graden. Er staat een matige tot vrij krachtige zuidwestenwind met rukwinden tot 60 km/h.", + "fr": "Ce soir et cette nuit, une (faible) perturbation traversera le pays d'ouest en est avec un peu de pluie ou quelques averses. A l'arrière, le ciel se dégagera. A l'aube, le zone de précipitations quittera progressivement le pays par le sud-est. Les minima varieront de 4 à 9 degrés, sous un vent modéré à assez fort de sud-ouest. Les rafales pourront atteindre des valeurs de 60 km/h." + }, + "dawnRiseSeconds": "31440", + "dawnSetSeconds": "60180", + "tempMin": 9, + "tempMax": null, + "ww1": 6, + "ww2": 3, + "wwevol": 0, + "ff1": 5, + "ff2": 4, + "ffevol": 0, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 29, + "peakSpeed": "55", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 100, + "precipQuantity": "1" + }, + { + "dayName": { + "fr": "Jeudi", + "nl": "Donderdag", + "en": "Thursday", + "de": "Donnerstag" + }, + "period": "3", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Morgen wisselen opklaringen en wolken elkaar af, waaruit plaatselijk enkele buien kunnen vallen. Aan het begin van de dag hangt er in de Ardennen veel lage bewolking. Het is vrij winderig en zeer zacht met maxima van 7 graden in de Hoge Ardennen tot 11 graden over het westen van het land. De zuidwestenwind is matig tot vrij krachtig met windstoten tot 65 km/h.", + "fr": "Demain, nuages et éclaircies se partageront le ciel avec quelques averses isolées. En début de journée, les nuages bas pourraient encore s'accrocher sur l'Ardenne. Le temps sera assez venteux et très doux avec des maxima de 7 degrés en Haute Ardenne à 11 degrés sur l'ouest du pays. Le vent de sud-ouest sera modéré à assez fort, avec des rafales jusqu'à 65 km/h." + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60180", + "tempMin": 9, + "tempMax": 11, + "ww1": 1, + "ww2": 3, + "wwevol": 0, + "ff1": 5, + "ff2": 4, + "ffevol": 1, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 29, + "peakSpeed": "60", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 0, + "precipQuantity": "0" + }, + { + "dayName": { + "fr": "Vendredi", + "nl": "Vrijdag", + "en": "Friday", + "de": "Freitag" + }, + "period": "5", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Vrijdag is het wisselvallig en winderig. Bij momenten vallen er intense regenbuien. De maxima klimmen naar waarden tussen 7 en 11 graden bij een vrij krachtige zuidwestenwind. Er zijn rukwinden mogelijk tot 70 km/h.", + "fr": "Vendredi, le temps sera variable, doux et venteux. De nouvelles pluies parfois abondantes et sous forme d'averses traverseront notre pays. Les maxima varieront entre 7 et 11 degrés avec un vent assez fort de sud-ouest. Les rafales pourront atteindre 70 km/h." + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60240", + "tempMin": 9, + "tempMax": 10, + "ww1": 6, + "ww2": 3, + "wwevol": 0, + "ff1": 5, + "ff2": 4, + "ffevol": 1, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 29, + "peakSpeed": "55", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 100, + "precipQuantity": "1" + }, + { + "dayName": { + "fr": "Samedi", + "nl": "Zaterdag", + "en": "Saturday", + "de": "Samstag" + }, + "period": "7", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Zaterdagvoormiddag is het vaak droog met tijdelijk opklaringen. In de loop van de dag neemt de bewolking toe, gevolgd door regen vanuit het westen. De maxima schommelen tussen 5 en 10 graden. De wind wordt vrij krachtig en krachtig aan zee uit zuidwest.", + "fr": "Samedi matin, le temps sera souvent sec avec temporairement des éclaircies. Dans le courant de la journée, la nébulosité augmentera, et sera suivie de pluies depuis l'ouest. Les maxima varieront entre 5 et 10 degrés. Le vent de sud-ouest sera assez fort, à fort le long du littoral." + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60300", + "tempMin": 4, + "tempMax": 8, + "ww1": 1, + "ww2": 15, + "wwevol": 0, + "ff1": 3, + "ff2": 4, + "ffevol": 0, + "dd": 22, + "ddText": { + "fr": "SSO", + "nl": "ZZW", + "en": "SSW", + "de": "SSW" + }, + "wind": { + "speed": 20, + "peakSpeed": null, + "dir": 22, + "dirText": { + "fr": "SSO", + "nl": "ZZW", + "en": "SSW", + "de": "SSW" + } + }, + "precipChance": 0, + "precipQuantity": "0" + }, + { + "dayName": { + "fr": "Dimanche", + "nl": "Zondag", + "en": "Sunday", + "de": "Sonntag" + }, + "period": "9", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Zondagochtend verlaat een actieve regenzone ons land via het zuidoosten. Daarachter wordt het wisselvallig met buien. De maxima schommelen tussen 5 en 8 graden. De wind is vrij krachtig en ruimt van zuidwest naar west.", + "fr": "Dimanche matin, une zone de pluie active finira de traverser notre pays et le quittera rapidement par le sud-est. A l'arrière, on retrouvera un temps variable avec des averses. Les maxima varieront entre 5 et 8 degrés. Le vent sera assez fort et virera du sud-ouest à l'ouest. " + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60360", + "tempMin": 7, + "tempMax": 9, + "ww1": 19, + "ww2": null, + "wwevol": null, + "ff1": 4, + "ff2": 6, + "ffevol": 0, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 39, + "peakSpeed": "90", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 100, + "precipQuantity": "14" + }, + { + "dayName": { + "fr": "Lundi", + "nl": "Maandag", + "en": "Monday", + "de": "Montag" + }, + "period": "11", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Maandag blijft het overwegend droog met tijdelijk brede opklaringen. De maxima schommelen tussen 3 en 7 graden.", + "fr": "Lundi, le temps restera généralement sec avec temporairement de larges éclaircies. Les maxima varieront entre 3 et 7 degrés. " + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60420", + "tempMin": 3, + "tempMax": 6, + "ww1": 6, + "ww2": null, + "wwevol": null, + "ff1": 5, + "ff2": null, + "ffevol": null, + "dd": 67, + "ddText": { + "fr": "OSO", + "nl": "WZW", + "en": "WSW", + "de": "WSW" + }, + "wind": { + "speed": 29, + "peakSpeed": "65", + "dir": 67, + "dirText": { + "fr": "OSO", + "nl": "WZW", + "en": "WSW", + "de": "WSW" + } + }, + "precipChance": 100, + "precipQuantity": "3" + }, + { + "dayName": { + "fr": "Mardi", + "nl": "Dinsdag", + "en": "Tuesday", + "de": "Dienstag" + }, + "period": "13", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Dinsdag komt er opnieuw meer bewolking en stijgt de kans op neerslag. Maxima rond 6 graden in het centrum van het land.", + "fr": "Mardi, on prévoit à nouveau davantage de nuages et une augmentation du risque de précipitations. Les maxima varieront autour de 6 degrés dans le centre du pays. " + }, + "dawnRiseSeconds": "31500", + "dawnSetSeconds": "60480", + "tempMin": 2, + "tempMax": 5, + "ww1": 1, + "ww2": null, + "wwevol": null, + "ff1": 3, + "ff2": 2, + "ffevol": 0, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 12, + "peakSpeed": null, + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 50, + "precipQuantity": "0" + } + ], + "showWarningTab": false, + "graph": { + "svg": [ + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=tx&l=nl&k=893edb0ba7a2f14a0189838896ee8a2e", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=tx&l=fr&k=893edb0ba7a2f14a0189838896ee8a2e", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=tx&l=en&k=893edb0ba7a2f14a0189838896ee8a2e", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=tx&l=de&k=893edb0ba7a2f14a0189838896ee8a2e" + }, + "ratio": 1.3638709677419354 + }, + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=tn&l=nl&k=893edb0ba7a2f14a0189838896ee8a2e", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=tn&l=fr&k=893edb0ba7a2f14a0189838896ee8a2e", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=tn&l=en&k=893edb0ba7a2f14a0189838896ee8a2e", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=tn&l=de&k=893edb0ba7a2f14a0189838896ee8a2e" + }, + "ratio": 1.3638709677419354 + }, + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=rr&l=nl&k=893edb0ba7a2f14a0189838896ee8a2e", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=rr&l=fr&k=893edb0ba7a2f14a0189838896ee8a2e", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=rr&l=en&k=893edb0ba7a2f14a0189838896ee8a2e", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=rr&l=de&k=893edb0ba7a2f14a0189838896ee8a2e" + }, + "ratio": 1.3638709677419354 + } + ] + }, + "hourly": [ + { + "hour": "11", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "12", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "13", + "temp": 11, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "14", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "15", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "16", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "17", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "18", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "19", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "20", + "temp": 10, + "ww": "15", + "precipChance": "30", + "precipQuantity": 0.02, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "21", + "temp": 10, + "ww": "18", + "precipChance": "70", + "precipQuantity": 0.79, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "22", + "temp": 9, + "ww": "18", + "precipChance": "70", + "precipQuantity": 0.16, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "23", + "temp": 9, + "ww": "15", + "precipChance": "30", + "precipQuantity": 0, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "00", + "temp": 10, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n", + "dateShow": "28/12", + "dateShowLocalized": { + "nl": "Don.", + "fr": "Jeu.", + "en": "Thu.", + "de": "Don." + } + }, + { + "hour": "01", + "temp": 10, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "02", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "03", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "04", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "05", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "06", + "temp": 10, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "07", + "temp": 9, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "08", + "temp": 9, + "ww": "0", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "09", + "temp": 9, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "10", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "11", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "12", + "temp": 10, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "13", + "temp": 11, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 35, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "14", + "temp": 11, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 30, + "windPeakSpeedKm": 60, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "15", + "temp": 11, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 25, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "16", + "temp": 11, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "17", + "temp": 10, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "18", + "temp": 10, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "19", + "temp": 10, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "20", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "21", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "22", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "23", + "temp": 9, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "00", + "temp": 9, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n", + "dateShow": "29/12", + "dateShowLocalized": { + "nl": "Vri.", + "fr": "Ven.", + "en": "Fri.", + "de": "Fre." + } + }, + { + "hour": "01", + "temp": 9, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0.02, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "02", + "temp": 10, + "ww": "15", + "precipChance": "20", + "precipQuantity": 0.02, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "03", + "temp": 10, + "ww": "14", + "precipChance": "40", + "precipQuantity": 0.04, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 60, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "04", + "temp": 10, + "ww": "18", + "precipChance": "40", + "precipQuantity": 0.11, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "05", + "temp": 10, + "ww": "18", + "precipChance": "40", + "precipQuantity": 0.26, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "06", + "temp": 10, + "ww": "14", + "precipChance": "50", + "precipQuantity": 0.07, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "07", + "temp": 9, + "ww": "15", + "precipChance": "60", + "precipQuantity": 0.09, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "08", + "temp": 9, + "ww": "18", + "precipChance": "60", + "precipQuantity": 0.26, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "09", + "temp": 9, + "ww": "18", + "precipChance": "60", + "precipQuantity": 0.11, + "pressure": 1009, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "10", + "temp": 9, + "ww": "6", + "precipChance": "70", + "precipQuantity": 0.14, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "11", + "temp": 10, + "ww": "3", + "precipChance": "50", + "precipQuantity": 0.04, + "pressure": 1010, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "d" + } + ], + "warning": [] + }, + "module": [ + { + "type": "svg", + "data": { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=pollen&l=nl&k=893edb0ba7a2f14a0189838896ee8a2e", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=pollen&l=fr&k=893edb0ba7a2f14a0189838896ee8a2e", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=pollen&l=en&k=893edb0ba7a2f14a0189838896ee8a2e", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=21004&e=pollen&l=de&k=893edb0ba7a2f14a0189838896ee8a2e" + }, + "ratio": 3.0458333333333334 + } + }, + { + "type": "uv", + "data": { + "levelValue": 0.6, + "level": { + "nl": "Laag", + "fr": "Faible", + "en": "Low", + "de": "Niedrig" + }, + "title": { + "nl": "Uv-index", + "fr": "Indice UV", + "en": "UV Index", + "de": "UV Index" + } + } + }, + { + "type": "observation", + "data": { + "count": 313, + "title": { + "nl": "Waarnemingen vandaag", + "fr": "Observations d'aujourd'hui", + "en": "Today's Observations", + "de": "Beobachtungen heute" + } + } + }, + { + "type": "svg", + "data": { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=nl&k=893edb0ba7a2f14a0189838896ee8a2e", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=fr&k=893edb0ba7a2f14a0189838896ee8a2e", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=en&k=893edb0ba7a2f14a0189838896ee8a2e", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=de&k=893edb0ba7a2f14a0189838896ee8a2e" + }, + "ratio": 1.6587926509186353 + } + } + ], + "animation": { + "localisationLayer": "https://app.meteo.be/services/appv4/?s=getLocalizationLayer&lat=50.797798&long=4.35811&f=2&k=3040f09e112c427d871465dc145bc9eb", + "localisationLayerRatioX": 0.5821, + "localisationLayerRatioY": 0.4118, + "speed": 0.3, + "type": "10min", + "unit": { + "fr": "mm/10min", + "nl": "mm/10min", + "en": "mm/10min", + "de": "mm/10min" + }, + "country": "BE", + "sequence": [ + { + "time": "2023-12-27T10:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312270910&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T10:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312270920&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T10:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312270930&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T10:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312270940&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T10:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312270950&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T10:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271000&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T11:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271010&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T11:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271020&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T11:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271030&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T11:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271040&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T11:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271050&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T11:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271100&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T12:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271110&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T12:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271120&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T12:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271130&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T12:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271140&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T12:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271150&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T12:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271200&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T13:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271210&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T13:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271220&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T13:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271230&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T13:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271240&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T13:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271250&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T13:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271300&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T14:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271310&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T14:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271320&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T14:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271330&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T14:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271340&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T14:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271350&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2023-12-27T14:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202312271400&f=2&k=5a1e5e23504a65226afb1775a7020ef0&d=202312271020", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + } + ], + "threshold": [], + "sequenceHint": { + "nl": "Geen regen voorzien op korte termijn", + "fr": "Pas de pluie prévue prochainement", + "en": "No rain forecasted shortly", + "de": "Kein Regen erwartet in naher Zukunft" + } + }, + "todayObsCount": 313 +} diff --git a/tests/components/irm_kmi/fixtures/high_low_temp.json b/tests/components/irm_kmi/fixtures/high_low_temp.json new file mode 100644 index 00000000000..f1b0e020a4a --- /dev/null +++ b/tests/components/irm_kmi/fixtures/high_low_temp.json @@ -0,0 +1,1635 @@ +{ + "cityName": "Namur", + "country": "BE", + "obs": { + "temp": 4, + "timestamp": "2024-01-21T14:10:00+01:00", + "ww": 15, + "dayNight": "d" + }, + "for": { + "daily": [ + { + "dayName": { + "fr": "Dimanche", + "nl": "Zondag", + "en": "Sunday", + "de": "Sonntag" + }, + "period": "1", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Deze namiddag is het vaak bewolkt en droog, op wat lokaal gedruppel na. Het wordt zachter met maxima van 1 of 2 graden in de Ardennen, 5 graden in het centrum tot 8 graden aan zee. De wind uit zuid tot zuidwest wordt soms vrij krachtig in het binnenland en krachtig aan zee. Verspreid over het land zijn er rukwinden mogelijk tussen 50 en 60 km/h.", + "fr": "Cet après-midi, il fera souvent nuageux mais sec à quelques gouttes près. Le temps sera plus doux avec des maxima de 1 ou 2 degrés en Ardenne, 5 degrés dans le centre jusqu'à 8 degrés à la mer. Le vent de sud à sud-ouest deviendra parfois assez fort dans l'intérieur et fort à la côte avec des rafales de 50 à 60 km/h." + }, + "dawnRiseSeconds": "30780", + "dawnSetSeconds": "62100", + "tempMin": null, + "tempMax": 3, + "ww1": 3, + "ww2": null, + "wwevol": null, + "ff1": 5, + "ff2": 4, + "ffevol": 1, + "dd": 22, + "ddText": { + "fr": "SSO", + "nl": "ZZW", + "en": "SSW", + "de": "SSW" + }, + "wind": { + "speed": 29, + "peakSpeed": "50", + "dir": 22, + "dirText": { + "fr": "SSO", + "nl": "ZZW", + "en": "SSW", + "de": "SSW" + } + }, + "precipChance": 0, + "precipQuantity": "0" + }, + { + "dayName": { + "fr": "Cette nuit", + "nl": "Vannacht", + "en": "Tonight", + "de": "heute abend" + }, + "period": "2", + "day_night": "0", + "dayNight": "n", + "text": { + "nl": "Vanavond en tijdens het eerste deel van de nacht is het bewolkt en meestal droog. Rond middernacht bereikt een regenzone ons land vanaf de kust en trekt verder oostwaarts. Dit gaat gepaard met meer wind. De wind uit zuidzuidwest spant aan tot krachtig in het binnenland en zeer krachtig aan zee met windstoten tussen 80 en 90 km/h (of zeer plaatselijk iets meer). De minima worden al vroeg tijdens de avond bereikt en liggen tussen 2 en 8 graden. Op het einde van de nacht klimmen de temperaturen naar waarden tussen 4 en 10 graden.", + "fr": "Ce soir et en première partie de nuit, le temps sera encore généralement sec. Autour de minuit, une zone de pluie atteindra le littoral avant de gagner les autres régions. Le vent de sud-sud-ouest se renforcera nettement pour devenir fort dans l'intérieur et très fort à la mer, avec des rafales de 80 à 90 km/h (ou très localement davantage). Les minima oscilleront entre 2 et 8 degrés (atteints en soirée). En fin de nuit, on relèvera 4 à 10 degrés." + }, + "dawnRiseSeconds": "30780", + "dawnSetSeconds": "62100", + "tempMin": 4, + "tempMax": null, + "ww1": 15, + "ww2": null, + "wwevol": null, + "ff1": 5, + "ff2": 6, + "ffevol": 0, + "dd": 22, + "ddText": { + "fr": "SSO", + "nl": "ZZW", + "en": "SSW", + "de": "SSW" + }, + "wind": { + "speed": 39, + "peakSpeed": "80", + "dir": 22, + "dirText": { + "fr": "SSO", + "nl": "ZZW", + "en": "SSW", + "de": "SSW" + } + }, + "precipChance": 35, + "precipQuantity": "0" + }, + { + "dayName": { + "fr": "Lundi", + "nl": "Maandag", + "en": "Monday", + "de": "Montag" + }, + "period": "3", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Maandag bereikt al snel een nieuwe regenzone ons land vanaf het westen. Aan de achterzijde hiervan wordt het grotendeels droog met brede opklaringen. De opklaringen doen zowel Laag- als Midden-België aan, in Hoog-België blijft het vermoedelijk bewolkt en regenachtig. Het wordt nog iets zachter bij maxima tussen 5 en 9 graden ten zuiden van Samber en Maas en 10 of 11 graden elders. In de voormiddag is de wind vaak nog krachtig in het binnenland en zeer krachtig aan zee met rukwinden tussen 80 en 90 km/h. In de namiddag, na de passage van de regenzone, ruimt de wind naar westelijke richtingen en wordt hij matig tot soms vrij krachtig in het binnenland en krachtig aan zee met rukwinden tussen 50 en 60 km/h.\n\nMaandagavond en -nacht is het vrijwel helder met soms enkele hoge wolkensluiers in Laag- en Midden-België. In Hoog-België domineren de lage wolkenvelden en kan er soms nog wat lichte regen of winterse neerslag vallen. De minima liggen tussen 1 en 6 graden. De wind uit westelijke richtingen is matig tot vrij krachtig in het binnenland en krachtig aan zee.", + "fr": "Lundi, une nouvelle zone de pluie atteindra rapidement le pays par l'ouest, suivie de belles éclaircies. En Haute Belgique, le temps restera pluvieux. Il fera encore plus doux avec des maxima de 5 à 9 degrés au sud du sillon Sambre et Meuse et de 10 ou 11 degrés ailleurs. Le vent sera encore assez fort le matin dans l'intérieur et très fort à la mer, avec des pointes de 80 à 90 km/h. L'après-midi, le vent tournera vers l'ouest et deviendra modéré à parfois assez fort, fort à la côte, avec des rafales de 50 à 60 km/h.\n\nLundi soir et la nuit de lundi à mardi, il fera peu nuageux avec parfois quelques voiles d'altitude. En Haute Belgique, les nuages bas domineront encore le ciel avec le risque de faibles pluies ou de précipitations hivernales. Les minima se situeront entre 1 et 6 degrés. Le vent de secteur ouest sera modéré à assez fort dans l'intérieur et fort à la mer." + }, + "dawnRiseSeconds": "30720", + "dawnSetSeconds": "62160", + "tempMin": 1, + "tempMax": 10, + "ww1": 18, + "ww2": 6, + "wwevol": 0, + "ff1": 6, + "ff2": 4, + "ffevol": 0, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 39, + "peakSpeed": "80", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 100, + "precipQuantity": "1" + }, + { + "dayName": { + "fr": "Mardi", + "nl": "Dinsdag", + "en": "Tuesday", + "de": "Dienstag" + }, + "period": "5", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Dinsdagochtend is het op veel plaatsen zonnig met hoge wolkenvelden. In de Ardennen begint de dag grijs met lokala mist. Vanaf het westen neemt de bewolking toe en volgt er regen. De maxima worden pas 's avonds laat bereikt; ze liggen dan tussen 7 of 8 graden in de Hoge Venen en 11 graden in Laag-België. De wind waait matig uit zuidwest, toenemend tot vrij krachtig en aan zee tot krachtig. Er zijn rukwinden mogelijk tot zo'n 60 km/h.", + "fr": "Mardi, la matinée sera souvent ensoleillée avec des voiles de nuages élevés. Les nuages bas et la grisaille recouvriront l'Ardenne. En cours de journée, la nébulosité augmentera à partir de l'ouest et des pluies suivront. Les maxima seront atteints en soirée et varieront entre 7 ou 8 degrés dans les Hautes Fagnes et 11 degrés en Basse Belgique. Le vent modéré de sud-ouest deviendra assez fort et même parfois fort le long du littoral avec des rafales autour de 60 km/h." + }, + "dawnRiseSeconds": "30660", + "dawnSetSeconds": "62280", + "tempMin": 3, + "tempMax": 8, + "ww1": 3, + "ww2": 18, + "wwevol": 0, + "ff1": 3, + "ff2": 5, + "ffevol": 0, + "dd": 45, + "ddText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + }, + "wind": { + "speed": 29, + "peakSpeed": "55", + "dir": 45, + "dirText": { + "fr": "SO", + "nl": "ZW", + "en": "SW", + "de": "SW" + } + }, + "precipChance": 50, + "precipQuantity": "1" + }, + { + "dayName": { + "fr": "Mercredi", + "nl": "Woensdag", + "en": "Wednesday", + "de": "Mittwoch" + }, + "period": "7", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Woensdagvoormiddag trekt een regenzone snel van noordwest naar zuidoost. In Vlaanderen wordt het snel droog met brede opklaringen. In de gebieden ten zuiden van Samber en Maas blijft het een groot deel van de dag grijs en regenachtig. De maxima liggen rond 6 of 7 graden in de Hoge Venen, rond 10 graden aan zee en rond 12 graden in het centrum. De wind waait vrij krachtig tot krachtig uit westzuidwest met rukwinden rond 65 km/h. Op het einde van de dag neemt de wind af.", + "fr": "Mercredi, une zone de pluie traversera notre pays du nord-ouest vers le sud-est. En Flandre, de larges éclaircies s'établiront rapidement mais la nébulosité restera abondante dans le sud du pays avec de la pluie. Les maxima oscilleront entre 6 ou 7 degrés en Hautes Fagnes, 10 degrés à la mer et 12 degrés dans le centre. Le vent sera assez fort à fort d'ouest-sud-ouest avec des pointes de 65 km/h. En fin de journée, le vent se calmera." + }, + "dawnRiseSeconds": "30600", + "dawnSetSeconds": "62340", + "tempMin": 12, + "tempMax": 10, + "ww1": 18, + "ww2": 4, + "wwevol": 0, + "ff1": 5, + "ff2": null, + "ffevol": null, + "dd": 90, + "ddText": { + "fr": "O", + "nl": "W", + "en": "W", + "de": "W" + }, + "wind": { + "speed": 29, + "peakSpeed": "70", + "dir": 90, + "dirText": { + "fr": "O", + "nl": "W", + "en": "W", + "de": "W" + } + }, + "precipChance": 100, + "precipQuantity": "2" + }, + { + "dayName": { + "fr": "Jeudi", + "nl": "Donderdag", + "en": "Thursday", + "de": "Donnerstag" + }, + "period": "9", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Donderdag start zonnig met hoge wolkenvelden. Ten zuiden van Samber en Maas begint de dag grijs met lage wolken en/of mist, die hardnekkig kunnen zijn. Geleidelijk neemt de bewolking toe vanaf het westen gevolgd door wat lichte regen. De maxima schommelen rond 9 graden in het centrum.", + "fr": "Jeudi, il fera d'abord ensoleillé avec des nuages élevés. Au sud du sillon Sambre et Meuse, le temps sera encore gris avec des nuages bas et/ou du brouillard tenace. Une faible zone de pluie suivra par l'ouest. Les maxima varieront autour de 9 degrés dans le centre." + }, + "dawnRiseSeconds": "30540", + "dawnSetSeconds": "62460", + "tempMin": 2, + "tempMax": 8, + "ww1": 15, + "ww2": null, + "wwevol": null, + "ff1": 2, + "ff2": 3, + "ffevol": 0, + "dd": 0, + "ddText": { + "fr": "S", + "nl": "Z", + "en": "S", + "de": "S" + }, + "wind": { + "speed": 12, + "peakSpeed": null, + "dir": 0, + "dirText": { + "fr": "S", + "nl": "Z", + "en": "S", + "de": "S" + } + }, + "precipChance": 0, + "precipQuantity": "0" + }, + { + "dayName": { + "fr": "Vendredi", + "nl": "Vrijdag", + "en": "Friday", + "de": "Freitag" + }, + "period": "11", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Vrijdag begint zwaarbewolkt met wat regen maar vanaf de kust wordt het vrij snel droog en vrij zonnig. In het zuiden blijft het veelal grijs met nog kans op buien. De maxima liggen in de buurt van 9 of 10 graden in het centrum.", + "fr": "Vendredi, il fera très nuageux avec un peu de pluie. Une belle amélioration se dessinera rapidement depuis la côte, excepté dans le sud du pays. Les maxima oscilleront autour de 9 ou 10 degrés dans le centre." + }, + "dawnRiseSeconds": "30480", + "dawnSetSeconds": "62580", + "tempMin": 6, + "tempMax": 8, + "ww1": 19, + "ww2": null, + "wwevol": null, + "ff1": 4, + "ff2": null, + "ffevol": null, + "dd": 135, + "ddText": { + "fr": "NO", + "nl": "NW", + "en": "NW", + "de": "NW" + }, + "wind": { + "speed": 20, + "peakSpeed": "50", + "dir": 135, + "dirText": { + "fr": "NO", + "nl": "NW", + "en": "NW", + "de": "NW" + } + }, + "precipChance": 100, + "precipQuantity": "2" + }, + { + "dayName": { + "fr": "Samedi", + "nl": "Zaterdag", + "en": "Saturday", + "de": "Samstag" + }, + "period": "13", + "day_night": "1", + "dayNight": "d", + "text": { + "nl": "Zaterdag is het vaak zonnig met middelhoge en hoge wolkenvelden. Later op de dag wordt de middelhoge bewolking wat dikker. De maxima liggen rond 7 graden in het centrum.", + "fr": "Samedi, il fera ensoleillé avec des champs nuageux de moyenne et de haute altitude. En cours de journée, la couverture de nuages moyens s'épaissira. Les maxima se situeront autour de 7 degrés dans le centre." + }, + "dawnRiseSeconds": "30360", + "dawnSetSeconds": "62700", + "tempMin": -2, + "tempMax": 6, + "ww1": 3, + "ww2": null, + "wwevol": null, + "ff1": 2, + "ff2": 3, + "ffevol": 0, + "dd": 0, + "ddText": { + "fr": "S", + "nl": "Z", + "en": "S", + "de": "S" + }, + "wind": { + "speed": 12, + "peakSpeed": null, + "dir": 0, + "dirText": { + "fr": "S", + "nl": "Z", + "en": "S", + "de": "S" + } + }, + "precipChance": 0, + "precipQuantity": "0" + } + ], + "showWarningTab": true, + "graph": { + "svg": [ + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tx&l=nl&k=32003c7eac2900f3d73c50f9e27330ab", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tx&l=fr&k=32003c7eac2900f3d73c50f9e27330ab", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tx&l=en&k=32003c7eac2900f3d73c50f9e27330ab", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tx&l=de&k=32003c7eac2900f3d73c50f9e27330ab" + }, + "ratio": 1.3638709677419354 + }, + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tn&l=nl&k=32003c7eac2900f3d73c50f9e27330ab", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tn&l=fr&k=32003c7eac2900f3d73c50f9e27330ab", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tn&l=en&k=32003c7eac2900f3d73c50f9e27330ab", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=tn&l=de&k=32003c7eac2900f3d73c50f9e27330ab" + }, + "ratio": 1.3638709677419354 + }, + { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=rr&l=nl&k=32003c7eac2900f3d73c50f9e27330ab", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=rr&l=fr&k=32003c7eac2900f3d73c50f9e27330ab", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=rr&l=en&k=32003c7eac2900f3d73c50f9e27330ab", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&ins=92094&e=rr&l=de&k=32003c7eac2900f3d73c50f9e27330ab" + }, + "ratio": 1.3638709677419354 + } + ] + }, + "hourly": [ + { + "hour": "14", + "temp": 3, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1022, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "d" + }, + { + "hour": "15", + "temp": 3, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1022, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "16", + "temp": 2, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1022, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "17", + "temp": 1, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1022, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + }, + { + "hour": "18", + "temp": 1, + "ww": "14", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1021, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "19", + "temp": 2, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1021, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "20", + "temp": 2, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1020, + "windSpeedKm": 35, + "windPeakSpeedKm": 60, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "21", + "temp": 3, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1019, + "windSpeedKm": 35, + "windPeakSpeedKm": 65, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "22", + "temp": 4, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1018, + "windSpeedKm": 40, + "windPeakSpeedKm": 70, + "windDirection": 0, + "windDirectionText": { + "nl": "Z", + "fr": "S", + "en": "S", + "de": "S" + }, + "dayNight": "n" + }, + { + "hour": "23", + "temp": 4, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0.01, + "pressure": 1017, + "windSpeedKm": 40, + "windPeakSpeedKm": 70, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "00", + "temp": 5, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0.08, + "pressure": 1016, + "windSpeedKm": 40, + "windPeakSpeedKm": 75, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n", + "dateShow": "22/01", + "dateShowLocalized": { + "nl": "Maa.", + "fr": "Lun.", + "en": "Mon.", + "de": "Mon." + } + }, + { + "hour": "01", + "temp": 6, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0.01, + "pressure": 1014, + "windSpeedKm": 45, + "windPeakSpeedKm": 75, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "02", + "temp": 7, + "ww": "18", + "precipChance": "20", + "precipQuantity": 0.1, + "pressure": 1014, + "windSpeedKm": 45, + "windPeakSpeedKm": 75, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "03", + "temp": 7, + "ww": "15", + "precipChance": "30", + "precipQuantity": 0.03, + "pressure": 1012, + "windSpeedKm": 45, + "windPeakSpeedKm": 80, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "04", + "temp": 8, + "ww": "18", + "precipChance": "30", + "precipQuantity": 0.21, + "pressure": 1011, + "windSpeedKm": 45, + "windPeakSpeedKm": 80, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "05", + "temp": 8, + "ww": "15", + "precipChance": "30", + "precipQuantity": 0.06, + "pressure": 1011, + "windSpeedKm": 45, + "windPeakSpeedKm": 80, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "06", + "temp": 9, + "ww": "15", + "precipChance": "30", + "precipQuantity": 0.09, + "pressure": 1011, + "windSpeedKm": 45, + "windPeakSpeedKm": 80, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "07", + "temp": 9, + "ww": "18", + "precipChance": "30", + "precipQuantity": 0.11, + "pressure": 1010, + "windSpeedKm": 45, + "windPeakSpeedKm": 80, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "n" + }, + { + "hour": "08", + "temp": 9, + "ww": "14", + "precipChance": "30", + "precipQuantity": 0.04, + "pressure": 1011, + "windSpeedKm": 40, + "windPeakSpeedKm": 75, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "09", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0.02, + "pressure": 1011, + "windSpeedKm": 35, + "windPeakSpeedKm": 70, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "10", + "temp": 9, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0.04, + "pressure": 1011, + "windSpeedKm": 30, + "windPeakSpeedKm": 65, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "11", + "temp": 9, + "ww": "3", + "precipChance": "30", + "precipQuantity": 0.06, + "pressure": 1012, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "d" + }, + { + "hour": "12", + "temp": 10, + "ww": "6", + "precipChance": "40", + "precipQuantity": 0.7100000000000001, + "pressure": 1012, + "windSpeedKm": 30, + "windPeakSpeedKm": 60, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "d" + }, + { + "hour": "13", + "temp": 9, + "ww": "18", + "precipChance": "40", + "precipQuantity": 0.22, + "pressure": 1012, + "windSpeedKm": 30, + "windPeakSpeedKm": 60, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "d" + }, + { + "hour": "14", + "temp": 8, + "ww": "15", + "precipChance": "40", + "precipQuantity": 0.03, + "pressure": 1012, + "windSpeedKm": 25, + "windPeakSpeedKm": 60, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "d" + }, + { + "hour": "15", + "temp": 7, + "ww": "3", + "precipChance": "20", + "precipQuantity": 0, + "pressure": 1012, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "d" + }, + { + "hour": "16", + "temp": 7, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1013, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "d" + }, + { + "hour": "17", + "temp": 6, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1014, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "d" + }, + { + "hour": "18", + "temp": 6, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1015, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "19", + "temp": 5, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1016, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "20", + "temp": 5, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1017, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "21", + "temp": 5, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1018, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "22", + "temp": 5, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0.02, + "pressure": 1019, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "23", + "temp": 5, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1019, + "windSpeedKm": 30, + "windPeakSpeedKm": 55, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "00", + "temp": 5, + "ww": "4", + "precipChance": "20", + "precipQuantity": 0.1, + "pressure": 1020, + "windSpeedKm": 30, + "windPeakSpeedKm": 50, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n", + "dateShow": "23/01", + "dateShowLocalized": { + "nl": "Din.", + "fr": "Mar.", + "en": "Tue.", + "de": "Die." + } + }, + { + "hour": "01", + "temp": 5, + "ww": "1", + "precipChance": "10", + "precipQuantity": 0.01, + "pressure": 1022, + "windSpeedKm": 25, + "windPeakSpeedKm": 55, + "windDirection": 90, + "windDirectionText": { + "nl": "W", + "fr": "O", + "en": "W", + "de": "W" + }, + "dayNight": "n" + }, + { + "hour": "02", + "temp": 4, + "ww": "1", + "precipChance": "10", + "precipQuantity": 0, + "pressure": 1022, + "windSpeedKm": 25, + "windPeakSpeedKm": 50, + "windDirection": 90, + "windDirectionText": { + "nl": "W", + "fr": "O", + "en": "W", + "de": "W" + }, + "dayNight": "n" + }, + { + "hour": "03", + "temp": 4, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1023, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 90, + "windDirectionText": { + "nl": "W", + "fr": "O", + "en": "W", + "de": "W" + }, + "dayNight": "n" + }, + { + "hour": "04", + "temp": 4, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1024, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "05", + "temp": 3, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1025, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "06", + "temp": 3, + "ww": "0", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1026, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 68, + "windDirectionText": { + "nl": "WZW", + "fr": "OSO", + "en": "WSW", + "de": "WSW" + }, + "dayNight": "n" + }, + { + "hour": "07", + "temp": 3, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1026, + "windSpeedKm": 15, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "08", + "temp": 3, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1027, + "windSpeedKm": 15, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "n" + }, + { + "hour": "09", + "temp": 3, + "ww": "1", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1028, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "10", + "temp": 4, + "ww": "3", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1028, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "11", + "temp": 6, + "ww": "15", + "precipChance": "0", + "precipQuantity": 0, + "pressure": 1028, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "12", + "temp": 6, + "ww": "15", + "precipChance": "20", + "precipQuantity": 0, + "pressure": 1029, + "windSpeedKm": 20, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "13", + "temp": 6, + "ww": "15", + "precipChance": "40", + "precipQuantity": 0.09, + "pressure": 1028, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 45, + "windDirectionText": { + "nl": "ZW", + "fr": "SO", + "en": "SW", + "de": "SW" + }, + "dayNight": "d" + }, + { + "hour": "14", + "temp": 7, + "ww": "18", + "precipChance": "60", + "precipQuantity": 0.2, + "pressure": 1027, + "windSpeedKm": 25, + "windPeakSpeedKm": null, + "windDirection": 23, + "windDirectionText": { + "nl": "ZZW", + "fr": "SSO", + "en": "SSW", + "de": "SSW" + }, + "dayNight": "d" + } + ], + "warning": [ + { + "icon_country": "BE", + "warningType": { + "id": "0", + "name": { + "fr": "Vent", + "nl": "Wind", + "en": "Wind", + "de": "Wind" + } + }, + "warningLevel": "1", + "text": { + "fr": "Ce soir et cette nuit, le vent se renforcera progressivement pour devenir fort dans l'intérieur et très fort à la mer. Des rafales de 80 à 90 km/h pourront se produire (très localement un peu plus). Lundi après-midi, les rafales se limiteront à des valeurs comprises entre 50 et 60 km/h.", + "nl": "Vanavond en vannacht spant de wind aan en wordt hij krachtig in het binnenland en zeer krachtig aan zee met rukwinden tussen 80 en 90 km/h (of zeer lokaal iets meer). Maandagnamiddag neemt hij af in kracht en zijn nog rukwinden mogelijk tussen 50 en 60 km/h.", + "en": "There is a strong wind expected where local troubles or damage is possible and traffic congestion may arise. Be careful.", + "de": "Es wird viel Wind erwartet, wobei lokale Beeinträchtigungen und Verkehrshindernisse entstehen können. Seien Sie vorsichtig." + }, + "fromTimestamp": "2024-01-21T23:00:00+01:00", + "toTimestamp": "2024-01-22T13:00:00+01:00" + } + ] + }, + "module": [ + { + "type": "uv", + "data": { + "levelValue": 0.7, + "level": { + "nl": "Laag", + "fr": "Faible", + "en": "Low", + "de": "Niedrig" + }, + "title": { + "nl": "Uv-index", + "fr": "Indice UV", + "en": "UV Index", + "de": "UV Index" + } + } + }, + { + "type": "observation", + "data": { + "count": 773, + "title": { + "nl": "Waarnemingen vandaag", + "fr": "Observations d'aujourd'hui", + "en": "Today's Observations", + "de": "Beobachtungen heute" + } + } + }, + { + "type": "svg", + "data": { + "url": { + "nl": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=nl&k=32003c7eac2900f3d73c50f9e27330ab", + "fr": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=fr&k=32003c7eac2900f3d73c50f9e27330ab", + "en": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=en&k=32003c7eac2900f3d73c50f9e27330ab", + "de": "https://app.meteo.be/services/appv4/?s=getSvg&e=efem&l=de&k=32003c7eac2900f3d73c50f9e27330ab" + }, + "ratio": 1.6587926509186353 + } + } + ], + "animation": { + "localisationLayer": "https://app.meteo.be/services/appv4/?s=getLocalizationLayerBE&ins=92094&f=2&k=83d708d73ec391c032e6d5fb70f7e71a", + "localisationLayerRatioX": 0.6667, + "localisationLayerRatioY": 0.523, + "speed": 0.3, + "type": "10min", + "unit": { + "fr": "mm/10min", + "nl": "mm/10min", + "en": "mm/10min", + "de": "mm/10min" + }, + "country": "BE", + "sequence": [ + { + "time": "2024-01-21T13:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211210&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T13:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211220&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T13:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211230&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T13:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211240&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T13:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211250&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T13:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211300&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T14:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211310&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T14:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211320&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T14:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211330&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T14:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211340&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T14:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211350&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T14:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211400&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T15:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211410&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T15:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211420&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T15:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211430&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T15:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211440&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T15:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211450&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T15:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211500&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T16:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211510&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T16:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211520&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T16:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211530&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T16:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211540&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T16:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211550&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T16:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211600&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T17:00:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211610&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T17:10:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211620&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T17:20:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211630&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T17:30:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211640&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T17:40:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211650&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + }, + { + "time": "2024-01-21T17:50:00+01:00", + "uri": "https://app.meteo.be/services/appv4/?s=getIncaImage&i=202401211700&f=2&k=c271685a8fd5ae335b2aa85654212f23&d=202401211310", + "value": 0, + "position": 0, + "positionLower": 0, + "positionHigher": 0 + } + ], + "threshold": [], + "sequenceHint": { + "nl": "Geen regen voorzien op korte termijn", + "fr": "Pas de pluie prévue prochainement", + "en": "No rain forecasted shortly", + "de": "Kein Regen erwartet in naher Zukunft" + } + }, + "todayObsCount": 773 +} diff --git a/tests/components/irm_kmi/snapshots/test_weather.ambr b/tests/components/irm_kmi/snapshots/test_weather.ambr new file mode 100644 index 00000000000..a8a0c92b539 --- /dev/null +++ b/tests/components/irm_kmi/snapshots/test_weather.ambr @@ -0,0 +1,694 @@ +# serializer version: 1 +# name: test_forecast_service[daily] + dict({ + 'weather.home': dict({ + 'forecast': list([ + dict({ + 'condition': 'pouring', + 'condition_2': None, + 'condition_evol': , + 'datetime': '2023-12-28', + 'is_daytime': True, + 'precipitation': 0.1, + 'precipitation_probability': None, + 'sunrise': '2023-12-28T08:47:43+01:00', + 'sunset': '2023-12-28T16:34:06+01:00', + 'temperature': 11.0, + 'templow': 9.0, + 'text': ''' + Waarschuwingen + Vanavond zijn er in het noordwesten zware windstoten mogelijk van 75-90 km/uur (code geel). + + Vanochtend is het half bewolkt met in het noorden kans op een bui. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, af en toe even stormachtig, windkracht 8. Aan de kust komen windstoten voor van ongeveer 80 km/uur. + Vanmiddag is het half tot zwaar bewolkt met kans op een bui, vooral in het noorden en westen. De middagtemperatuur ligt rond 11°C. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust krachtig tot hard, windkracht 6-7, vooral later ook af en toe stormachtig, windkracht 8. Aan de kust zijn er windstoten tot ongeveer 80 km/uur. + Vanavond zijn er buien, alleen in het zuidoosten is het overwegend droog. De wind komt uit het zuidwesten en is meestal vrij krachtig, aan de kust hard tot stormachtig, windkracht 7 tot 8. Vooral in het noordwesten zijn windstoten mogelijk van 75-90 km/uur. + + Komende nacht komen er enkele buien voor. Met een minimumtemperatuur van ongeveer 8°C is het zacht. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met zware windstoten tot ongeveer 80 km/uur. + + Morgenochtend is het half tot zwaar bewolkt en zijn er enkele buien. De wind komt uit het zuidwesten en is matig tot vrij krachtig, aan zee krachtig hard, windkracht 6-7, met vooral in het noordwesten mogelijk zware windstoten tot ongeveer 80 km/uur. + Morgenmiddag is er af en toe ruimte voor de zon en blijft het op de meeste plaatsen droog, alleen in het zuidoosten kan een enkele bui vallen. Met middagtemperaturen van ongeveer 10°C blijft het zacht. De wind uit het zuidwesten is matig tot vrij krachtig, aan zee krachtig tot hard, windkracht 6-7, met in het Waddengebied zware windstoten tot ongeveer 80 km/uur. + Morgenavond is het half tot zwaar bewolkt met een enkele bui. De wind komt uit het zuidwesten en is meest matig, aan de kust krachtig tot hard, windkracht 6-7, boven de Wadden eerst stormachtig, windkracht 8. + (Bron: KNMI, 2023-12-28T06:56:00+01:00) + + ''', + 'wind_bearing': 225.0, + 'wind_gust_speed': 33.0, + 'wind_speed': 32.0, + }), + dict({ + 'condition': 'partlycloudy', + 'condition_2': None, + 'condition_evol': , + 'datetime': '2023-12-29', + 'is_daytime': True, + 'precipitation': 3.8, + 'precipitation_probability': None, + 'sunrise': '2023-12-29T08:47:48+01:00', + 'sunset': '2023-12-29T16:35:00+01:00', + 'temperature': 10.0, + 'text': '', + 'wind_bearing': 248.0, + 'wind_gust_speed': 28.0, + 'wind_speed': 26.0, + }), + dict({ + 'condition': 'pouring', + 'condition_2': None, + 'condition_evol': , + 'datetime': '2023-12-30', + 'is_daytime': True, + 'precipitation': 1.7, + 'precipitation_probability': None, + 'sunrise': '2023-12-30T08:47:49+01:00', + 'sunset': '2023-12-30T16:35:57+01:00', + 'temperature': 10.0, + 'templow': 5.0, + 'text': '', + 'wind_bearing': 225.0, + 'wind_gust_speed': 25.0, + 'wind_speed': 22.0, + }), + dict({ + 'condition': 'pouring', + 'condition_2': None, + 'condition_evol': , + 'datetime': '2023-12-31', + 'is_daytime': True, + 'precipitation': 4.2, + 'precipitation_probability': None, + 'sunrise': '2023-12-31T08:47:47+01:00', + 'sunset': '2023-12-31T16:36:56+01:00', + 'temperature': 9.0, + 'templow': 7.0, + 'text': '', + 'wind_bearing': 203.0, + 'wind_gust_speed': 31.0, + 'wind_speed': 30.0, + }), + dict({ + 'condition': 'pouring', + 'condition_2': None, + 'condition_evol': , + 'datetime': '2024-01-01', + 'is_daytime': True, + 'precipitation': 2.2, + 'precipitation_probability': None, + 'sunrise': '2024-01-01T08:47:42+01:00', + 'sunset': '2024-01-01T16:37:59+01:00', + 'temperature': 7.0, + 'templow': 5.0, + 'text': '', + 'wind_bearing': 225.0, + 'wind_gust_speed': 28.0, + 'wind_speed': 23.0, + }), + dict({ + 'condition': 'pouring', + 'condition_2': None, + 'condition_evol': , + 'datetime': '2024-01-02', + 'is_daytime': True, + 'precipitation': 1.4, + 'precipitation_probability': None, + 'sunrise': '2024-01-02T08:47:32+01:00', + 'sunset': '2024-01-02T16:39:04+01:00', + 'temperature': 6.0, + 'templow': 3.0, + 'text': '', + 'wind_bearing': 225.0, + 'wind_gust_speed': 16.0, + 'wind_speed': 15.0, + }), + dict({ + 'condition': 'pouring', + 'condition_2': None, + 'condition_evol': , + 'datetime': '2024-01-03', + 'is_daytime': True, + 'precipitation': 1.0, + 'precipitation_probability': None, + 'sunrise': '2024-01-03T08:47:20+01:00', + 'sunset': '2024-01-03T16:40:12+01:00', + 'temperature': 6.0, + 'templow': 3.0, + 'text': '', + 'wind_bearing': 203.0, + 'wind_gust_speed': 14.0, + 'wind_speed': 13.0, + }), + ]), + }), + }) +# --- +# name: test_forecast_service[hourly] + dict({ + 'weather.home': dict({ + 'forecast': list([ + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-22T15:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1008.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 33.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-22T16:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1008.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 32.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-22T17:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1007.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 32.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-22T18:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1007.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 35.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-22T19:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 35.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-22T20:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 35.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-22T21:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 35.0, + }), + dict({ + 'condition': 'pouring', + 'datetime': '2025-09-22T22:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.7, + 'precipitation_probability': 70, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 35.0, + }), + dict({ + 'condition': 'pouring', + 'datetime': '2025-09-22T23:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.1, + 'precipitation_probability': 10, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 37.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-23T00:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 20, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 35.0, + }), + dict({ + 'condition': 'pouring', + 'datetime': '2025-09-23T01:00:00+02:00', + 'is_daytime': False, + 'precipitation': 1.9, + 'precipitation_probability': 80, + 'pressure': 1005.0, + 'temperature': 10.0, + 'wind_bearing': 225.0, + 'wind_speed': 31.0, + }), + dict({ + 'condition': 'pouring', + 'datetime': '2025-09-23T02:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.6, + 'precipitation_probability': 70, + 'pressure': 1005.0, + 'temperature': 10.0, + 'wind_bearing': 248.0, + 'wind_speed': 38.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T03:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1005.0, + 'temperature': 10.0, + 'wind_bearing': 248.0, + 'wind_speed': 35.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-23T04:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1005.0, + 'temperature': 10.0, + 'wind_bearing': 248.0, + 'wind_speed': 34.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T05:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1005.0, + 'temperature': 9.0, + 'wind_bearing': 248.0, + 'wind_speed': 35.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-23T06:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1005.0, + 'temperature': 9.0, + 'wind_bearing': 248.0, + 'wind_speed': 34.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T07:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1005.0, + 'temperature': 9.0, + 'wind_bearing': 248.0, + 'wind_speed': 32.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T08:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1005.0, + 'temperature': 9.0, + 'wind_bearing': 248.0, + 'wind_speed': 31.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T09:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1005.0, + 'temperature': 9.0, + 'wind_bearing': 248.0, + 'wind_speed': 31.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-23T10:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1005.0, + 'temperature': 9.0, + 'wind_bearing': 248.0, + 'wind_speed': 32.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T11:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 248.0, + 'wind_speed': 32.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T12:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 248.0, + 'wind_speed': 34.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T13:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 248.0, + 'wind_speed': 33.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T14:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 248.0, + 'wind_speed': 31.0, + }), + dict({ + 'condition': 'sunny', + 'datetime': '2025-09-23T15:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 10.0, + 'wind_bearing': 248.0, + 'wind_speed': 28.0, + }), + dict({ + 'condition': 'sunny', + 'datetime': '2025-09-23T16:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 9.0, + 'wind_bearing': 248.0, + 'wind_speed': 24.0, + }), + dict({ + 'condition': 'clear-night', + 'datetime': '2025-09-23T17:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 8.0, + 'wind_bearing': 225.0, + 'wind_speed': 20.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T18:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 8.0, + 'wind_bearing': 225.0, + 'wind_speed': 18.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-23T19:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1005.0, + 'temperature': 8.0, + 'wind_bearing': 203.0, + 'wind_speed': 15.0, + }), + dict({ + 'condition': 'pouring', + 'datetime': '2025-09-23T20:00:00+02:00', + 'is_daytime': False, + 'precipitation': 5.7, + 'precipitation_probability': 100, + 'pressure': 1005.0, + 'temperature': 8.0, + 'wind_bearing': 248.0, + 'wind_speed': 22.0, + }), + dict({ + 'condition': 'pouring', + 'datetime': '2025-09-23T21:00:00+02:00', + 'is_daytime': False, + 'precipitation': 3.8, + 'precipitation_probability': 100, + 'pressure': 1006.0, + 'temperature': 7.0, + 'wind_bearing': 270.0, + 'wind_speed': 26.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-23T22:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1006.0, + 'temperature': 8.0, + 'wind_bearing': 248.0, + 'wind_speed': 24.0, + }), + dict({ + 'condition': 'cloudy', + 'datetime': '2025-09-23T23:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1007.0, + 'temperature': 7.0, + 'wind_bearing': 248.0, + 'wind_speed': 22.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-24T00:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1008.0, + 'temperature': 8.0, + 'wind_bearing': 270.0, + 'wind_speed': 26.0, + }), + dict({ + 'condition': 'clear-night', + 'datetime': '2025-09-24T01:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1007.0, + 'temperature': 7.0, + 'wind_bearing': 270.0, + 'wind_speed': 26.0, + }), + dict({ + 'condition': 'clear-night', + 'datetime': '2025-09-24T02:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1008.0, + 'temperature': 7.0, + 'wind_bearing': 270.0, + 'wind_speed': 24.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-24T03:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1008.0, + 'temperature': 7.0, + 'wind_bearing': 270.0, + 'wind_speed': 24.0, + }), + dict({ + 'condition': 'clear-night', + 'datetime': '2025-09-24T04:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1009.0, + 'temperature': 7.0, + 'wind_bearing': 248.0, + 'wind_speed': 23.0, + }), + dict({ + 'condition': 'clear-night', + 'datetime': '2025-09-24T05:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1009.0, + 'temperature': 6.0, + 'wind_bearing': 248.0, + 'wind_speed': 23.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-24T06:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1009.0, + 'temperature': 6.0, + 'wind_bearing': 248.0, + 'wind_speed': 21.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-24T07:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1010.0, + 'temperature': 6.0, + 'wind_bearing': 248.0, + 'wind_speed': 20.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-24T08:00:00+02:00', + 'is_daytime': False, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1011.0, + 'temperature': 6.0, + 'wind_bearing': 248.0, + 'wind_speed': 17.0, + }), + dict({ + 'condition': 'sunny', + 'datetime': '2025-09-24T09:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1011.0, + 'temperature': 6.0, + 'wind_bearing': 248.0, + 'wind_speed': 13.0, + }), + dict({ + 'condition': 'partlycloudy', + 'datetime': '2025-09-24T10:00:00+02:00', + 'is_daytime': True, + 'precipitation': 0.0, + 'precipitation_probability': 0, + 'pressure': 1012.0, + 'temperature': 5.0, + 'wind_bearing': 225.0, + 'wind_speed': 12.0, + }), + ]), + }), + }) +# --- +# name: test_weather_nl[weather.home-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'weather', + 'entity_category': None, + 'entity_id': 'weather.home', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'irm_kmi', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': 'city country', + 'unit_of_measurement': None, + }) +# --- +# name: test_weather_nl[weather.home-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Weather data from the Royal Meteorological Institute of Belgium meteo.be', + 'friendly_name': 'Home', + 'precipitation_unit': , + 'pressure': 1008.0, + 'pressure_unit': , + 'supported_features': , + 'temperature': 11.0, + 'temperature_unit': , + 'uv_index': 1, + 'visibility_unit': , + 'wind_bearing': 225.0, + 'wind_speed': 40.0, + 'wind_speed_unit': , + }), + 'context': , + 'entity_id': 'weather.home', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'cloudy', + }) +# --- diff --git a/tests/components/irm_kmi/test_config_flow.py b/tests/components/irm_kmi/test_config_flow.py new file mode 100644 index 00000000000..46eba74a7a5 --- /dev/null +++ b/tests/components/irm_kmi/test_config_flow.py @@ -0,0 +1,154 @@ +"""Tests for the IRM KMI config flow.""" + +from unittest.mock import MagicMock + +from homeassistant.components.irm_kmi.const import CONF_LANGUAGE_OVERRIDE, DOMAIN +from homeassistant.config_entries import SOURCE_USER +from homeassistant.const import ( + ATTR_LATITUDE, + ATTR_LONGITUDE, + CONF_LOCATION, + CONF_UNIQUE_ID, +) +from homeassistant.core import HomeAssistant +from homeassistant.data_entry_flow import FlowResultType + +from tests.common import MockConfigEntry + + +async def test_full_user_flow( + hass: HomeAssistant, + mock_setup_entry: MagicMock, + mock_get_forecast_in_benelux: MagicMock, +) -> None: + """Test the full user configuration flow.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + + assert result.get("type") is FlowResultType.FORM + assert result.get("step_id") == "user" + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={CONF_LOCATION: {ATTR_LATITUDE: 50.123, ATTR_LONGITUDE: 4.456}}, + ) + assert result.get("type") is FlowResultType.CREATE_ENTRY + assert result.get("title") == "Brussels" + assert result.get("data") == { + CONF_LOCATION: {ATTR_LATITUDE: 50.123, ATTR_LONGITUDE: 4.456}, + CONF_UNIQUE_ID: "brussels be", + } + + +async def test_user_flow_home( + hass: HomeAssistant, + mock_setup_entry: MagicMock, + mock_get_forecast_in_benelux: MagicMock, +) -> None: + """Test the full user configuration flow.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={CONF_LOCATION: {ATTR_LATITUDE: 50.123, ATTR_LONGITUDE: 4.456}}, + ) + assert result.get("type") is FlowResultType.CREATE_ENTRY + assert result.get("title") == "Brussels" + + +async def test_config_flow_location_out_benelux( + hass: HomeAssistant, + mock_setup_entry: MagicMock, + mock_get_forecast_out_benelux_then_in_belgium: MagicMock, +) -> None: + """Test configuration flow with a zone outside of Benelux.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={CONF_LOCATION: {ATTR_LATITUDE: 0.123, ATTR_LONGITUDE: 0.456}}, + ) + + assert result.get("type") is FlowResultType.FORM + assert result.get("step_id") == "user" + assert CONF_LOCATION in result.get("errors") + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={CONF_LOCATION: {ATTR_LATITUDE: 50.123, ATTR_LONGITUDE: 4.456}}, + ) + assert result.get("type") is FlowResultType.CREATE_ENTRY + + +async def test_config_flow_with_api_error( + hass: HomeAssistant, + mock_setup_entry: MagicMock, + mock_get_forecast_api_error: MagicMock, +) -> None: + """Test when API returns an error during the configuration flow.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={CONF_LOCATION: {ATTR_LATITUDE: 50.123, ATTR_LONGITUDE: 4.456}}, + ) + + assert result.get("type") is FlowResultType.ABORT + + +async def test_setup_twice_same_location( + hass: HomeAssistant, + mock_setup_entry: MagicMock, + mock_get_forecast_in_benelux: MagicMock, +) -> None: + """Test when the user tries to set up the weather twice for the same location.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={CONF_LOCATION: {ATTR_LATITUDE: 50.5, ATTR_LONGITUDE: 4.6}}, + ) + assert result.get("type") is FlowResultType.CREATE_ENTRY + + # Set up a second time + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": SOURCE_USER} + ) + + result = await hass.config_entries.flow.async_configure( + result["flow_id"], + user_input={CONF_LOCATION: {ATTR_LATITUDE: 50.5, ATTR_LONGITUDE: 4.6}}, + ) + assert result.get("type") is FlowResultType.ABORT + + +async def test_option_flow( + hass: HomeAssistant, mock_config_entry: MockConfigEntry +) -> None: + """Test when the user changes options with the option flow.""" + mock_config_entry.add_to_hass(hass) + + assert not mock_config_entry.options + + result = await hass.config_entries.options.async_init( + mock_config_entry.entry_id, data=None + ) + + assert result["type"] is FlowResultType.FORM + assert result["step_id"] == "init" + + result = await hass.config_entries.options.async_configure( + result["flow_id"], user_input={} + ) + + assert result["type"] is FlowResultType.CREATE_ENTRY + assert result["data"] == {CONF_LANGUAGE_OVERRIDE: "none"} diff --git a/tests/components/irm_kmi/test_init.py b/tests/components/irm_kmi/test_init.py new file mode 100644 index 00000000000..4fa310ab81a --- /dev/null +++ b/tests/components/irm_kmi/test_init.py @@ -0,0 +1,43 @@ +"""Tests for the IRM KMI integration.""" + +from unittest.mock import AsyncMock + +from homeassistant.components.irm_kmi.const import DOMAIN +from homeassistant.config_entries import ConfigEntryState +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry + + +async def test_load_unload_config_entry( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_irm_kmi_api: AsyncMock, +) -> None: + """Test the IRM KMI configuration entry loading/unloading.""" + mock_config_entry.add_to_hass(hass) + + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + assert mock_config_entry.state is ConfigEntryState.LOADED + + await hass.config_entries.async_unload(mock_config_entry.entry_id) + await hass.async_block_till_done() + + assert not hass.data.get(DOMAIN) + assert mock_config_entry.state is ConfigEntryState.NOT_LOADED + + +async def test_config_entry_not_ready( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_exception_irm_kmi_api: AsyncMock, +) -> None: + """Test the IRM KMI configuration entry not ready.""" + mock_config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + assert mock_exception_irm_kmi_api.refresh_forecasts_coord.call_count == 1 + assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY diff --git a/tests/components/irm_kmi/test_weather.py b/tests/components/irm_kmi/test_weather.py new file mode 100644 index 00000000000..c02a7171c5d --- /dev/null +++ b/tests/components/irm_kmi/test_weather.py @@ -0,0 +1,99 @@ +"""Test for the weather entity of the IRM KMI integration.""" + +from unittest.mock import AsyncMock + +import pytest +from syrupy.assertion import SnapshotAssertion + +from homeassistant.components.weather import ( + DOMAIN as WEATHER_DOMAIN, + SERVICE_GET_FORECASTS, +) +from homeassistant.const import ATTR_ENTITY_ID +from homeassistant.core import HomeAssistant +import homeassistant.helpers.entity_registry as er + +from tests.common import MockConfigEntry, snapshot_platform + + +@pytest.mark.freeze_time("2023-12-28T15:30:00+01:00") +async def test_weather_nl( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_irm_kmi_api_nl: AsyncMock, + snapshot: SnapshotAssertion, + entity_registry: er.EntityRegistry, +) -> None: + """Test weather with forecast from the Netherland.""" + mock_config_entry.add_to_hass(hass) + + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) + + +@pytest.mark.parametrize( + "forecast_type", + ["daily", "hourly"], +) +async def test_forecast_service( + hass: HomeAssistant, + snapshot: SnapshotAssertion, + mock_irm_kmi_api_nl: AsyncMock, + mock_config_entry: MockConfigEntry, + forecast_type: str, +) -> None: + """Test multiple forecast.""" + mock_config_entry.add_to_hass(hass) + + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + response = await hass.services.async_call( + WEATHER_DOMAIN, + SERVICE_GET_FORECASTS, + { + ATTR_ENTITY_ID: "weather.home", + "type": forecast_type, + }, + blocking=True, + return_response=True, + ) + assert response == snapshot + + +@pytest.mark.freeze_time("2024-01-21T14:15:00+01:00") +@pytest.mark.parametrize( + "forecast_type", + ["daily", "hourly"], +) +async def test_weather_higher_temp_at_night( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_irm_kmi_api_high_low_temp: AsyncMock, + forecast_type: str, +) -> None: + """Test that the templow is always lower than temperature, even when API returns the opposite.""" + # Test case for https://github.com/jdejaegh/irm-kmi-ha/issues/8 + mock_config_entry.add_to_hass(hass) + + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + response = await hass.services.async_call( + WEATHER_DOMAIN, + SERVICE_GET_FORECASTS, + { + ATTR_ENTITY_ID: "weather.home", + "type": forecast_type, + }, + blocking=True, + return_response=True, + ) + for forecast in response["weather.home"]["forecast"]: + assert ( + forecast.get("native_temperature") is None + or forecast.get("native_templow") is None + or forecast["native_temperature"] >= forecast["native_templow"] + )