diff --git a/CODEOWNERS b/CODEOWNERS index 0bb10972910..0f0757cb983 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -246,7 +246,7 @@ homeassistant/components/mcp23017/* @jardiamj homeassistant/components/mediaroom/* @dgomes homeassistant/components/melcloud/* @vilppuvuorinen homeassistant/components/melissa/* @kennedyshead -homeassistant/components/met/* @danielhiversen +homeassistant/components/met/* @danielhiversen @thimic homeassistant/components/meteo_france/* @hacf-fr @oncleben31 @Quentame homeassistant/components/meteoalarm/* @rolfberkenbosch homeassistant/components/metoffice/* @MrHarcombe diff --git a/homeassistant/components/met/__init__.py b/homeassistant/components/met/__init__.py index 1f5502170e4..4eedfc0b76d 100644 --- a/homeassistant/components/met/__init__.py +++ b/homeassistant/components/met/__init__.py @@ -22,9 +22,6 @@ import homeassistant.util.dt as dt_util from .const import CONF_TRACK_HOME, DOMAIN -URL = "https://api.met.no/weatherapi/locationforecast/2.0/classic" - - _LOGGER = logging.getLogger(__name__) @@ -142,7 +139,7 @@ class MetWeatherData: } self._weather_data = metno.MetWeatherData( - coordinates, async_get_clientsession(self.hass), URL + coordinates, async_get_clientsession(self.hass) ) async def fetch_data(self): diff --git a/homeassistant/components/met/const.py b/homeassistant/components/met/const.py index f29f034df68..8c507eb0b8d 100644 --- a/homeassistant/components/met/const.py +++ b/homeassistant/components/met/const.py @@ -1,7 +1,34 @@ """Constants for Met component.""" import logging -from homeassistant.components.weather import DOMAIN as WEATHER_DOMAIN +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, + ATTR_FORECAST_CONDITION, + ATTR_FORECAST_PRECIPITATION, + ATTR_FORECAST_PRECIPITATION_PROBABILITY, + ATTR_FORECAST_TEMP, + ATTR_FORECAST_TEMP_LOW, + ATTR_FORECAST_TIME, + ATTR_FORECAST_WIND_BEARING, + ATTR_FORECAST_WIND_SPEED, + ATTR_WEATHER_ATTRIBUTION, + ATTR_WEATHER_HUMIDITY, + ATTR_WEATHER_PRESSURE, + ATTR_WEATHER_TEMPERATURE, + ATTR_WEATHER_VISIBILITY, + ATTR_WEATHER_WIND_BEARING, + ATTR_WEATHER_WIND_SPEED, + DOMAIN as WEATHER_DOMAIN, +) DOMAIN = "met" @@ -11,4 +38,158 @@ CONF_TRACK_HOME = "track_home" ENTITY_ID_SENSOR_FORMAT_HOME = f"{WEATHER_DOMAIN}.met_{HOME_LOCATION_NAME}" +CONDITIONS_MAP = { + ATTR_CONDITION_CLEAR_NIGHT: {"clearsky_night"}, + ATTR_CONDITION_CLOUDY: {"cloudy_night", "cloudy_day", "cloudy"}, + ATTR_CONDITION_FOG: {"fog", "fog_day", "fog_night"}, + ATTR_CONDITION_LIGHTNING_RAINY: { + "heavyrainandthunder", + "heavyrainandthunder_day", + "heavyrainandthunder_night", + "heavyrainshowersandthunder", + "heavyrainshowersandthunder_day", + "heavyrainshowersandthunder_night", + "heavysleetandthunder", + "heavysleetandthunder_day", + "heavysleetandthunder_night", + "heavysleetshowersandthunder", + "heavysleetshowersandthunder_day", + "heavysleetshowersandthunder_night", + "heavysnowandthunder", + "heavysnowandthunder_day", + "heavysnowandthunder_night", + "heavysnowshowersandthunder", + "heavysnowshowersandthunder_day", + "heavysnowshowersandthunder_night", + "lightrainandthunder", + "lightrainandthunder_day", + "lightrainandthunder_night", + "lightrainshowersandthunder", + "lightrainshowersandthunder_day", + "lightrainshowersandthunder_night", + "lightsleetandthunder", + "lightsleetandthunder_day", + "lightsleetandthunder_night", + "lightsnowandthunder", + "lightsnowandthunder_day", + "lightsnowandthunder_night", + "lightssleetshowersandthunder", + "lightssleetshowersandthunder_day", + "lightssleetshowersandthunder_night", + "lightssnowshowersandthunder", + "lightssnowshowersandthunder_day", + "lightssnowshowersandthunder_night", + "rainandthunder", + "rainandthunder_day", + "rainandthunder_night", + "rainshowersandthunder", + "rainshowersandthunder_day", + "rainshowersandthunder_night", + "sleetandthunder", + "sleetandthunder_day", + "sleetandthunder_night", + "sleetshowersandthunder", + "sleetshowersandthunder_day", + "sleetshowersandthunder_night", + "snowshowersandthunder", + "snowshowersandthunder_day", + "snowshowersandthunder_night", + }, + ATTR_CONDITION_PARTLYCLOUDY: { + "fair", + "fair_day", + "fair_night", + "partlycloudy", + "partlycloudy_day", + "partlycloudy_night", + }, + ATTR_CONDITION_POURING: { + "heavyrain", + "heavyrain_day", + "heavyrain_night", + "heavyrainshowers", + "heavyrainshowers_day", + "heavyrainshowers_night", + }, + ATTR_CONDITION_RAINY: { + "lightrain", + "lightrain_day", + "lightrain_night", + "lightrainshowers", + "lightrainshowers_day", + "lightrainshowers_night", + "rain", + "rain_day", + "rain_night", + "rainshowers", + "rainshowers_day", + "rainshowers_night", + }, + ATTR_CONDITION_SNOWY: { + "heavysnow", + "heavysnow_day", + "heavysnow_night", + "heavysnowshowers", + "heavysnowshowers_day", + "heavysnowshowers_night", + "lightsnow", + "lightsnow_day", + "lightsnow_night", + "lightsnowshowers", + "lightsnowshowers_day", + "lightsnowshowers_night", + "snow", + "snow_day", + "snow_night", + "snowandthunder", + "snowandthunder_day", + "snowandthunder_night", + "snowshowers", + "snowshowers_day", + "snowshowers_night", + }, + ATTR_CONDITION_SNOWY_RAINY: { + "heavysleet", + "heavysleet_day", + "heavysleet_night", + "heavysleetshowers", + "heavysleetshowers_day", + "heavysleetshowers_night", + "lightsleet", + "lightsleet_day", + "lightsleet_night", + "lightsleetshowers", + "lightsleetshowers_day", + "lightsleetshowers_night", + "sleet", + "sleet_day", + "sleet_night", + "sleetshowers", + "sleetshowers_day", + "sleetshowers_night", + }, + ATTR_CONDITION_SUNNY: {"clearsky_day", "clearsky"}, +} + +FORECAST_MAP = { + ATTR_FORECAST_CONDITION: "condition", + ATTR_FORECAST_PRECIPITATION: "precipitation", + ATTR_FORECAST_PRECIPITATION_PROBABILITY: "precipitation_probability", + ATTR_FORECAST_TEMP: "temperature", + ATTR_FORECAST_TEMP_LOW: "templow", + ATTR_FORECAST_TIME: "datetime", + ATTR_FORECAST_WIND_BEARING: "wind_bearing", + ATTR_FORECAST_WIND_SPEED: "wind_speed", +} + +ATTR_MAP = { + ATTR_WEATHER_ATTRIBUTION: "attribution", + ATTR_WEATHER_HUMIDITY: "humidity", + ATTR_WEATHER_PRESSURE: "pressure", + ATTR_WEATHER_TEMPERATURE: "temperature", + ATTR_WEATHER_VISIBILITY: "visibility", + ATTR_WEATHER_WIND_BEARING: "wind_bearing", + ATTR_WEATHER_WIND_SPEED: "wind_speed", +} + _LOGGER = logging.getLogger(".") diff --git a/homeassistant/components/met/manifest.json b/homeassistant/components/met/manifest.json index 570e3df3bf0..38b77a0afd2 100644 --- a/homeassistant/components/met/manifest.json +++ b/homeassistant/components/met/manifest.json @@ -3,6 +3,6 @@ "name": "Meteorologisk institutt (Met.no)", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/met", - "requirements": ["pyMetno==0.7.1"], - "codeowners": ["@danielhiversen"] + "requirements": ["pyMetno==0.8.1"], + "codeowners": ["@danielhiversen", "@thimic"] } diff --git a/homeassistant/components/met/weather.py b/homeassistant/components/met/weather.py index e532c193e71..a53f66ab1dc 100644 --- a/homeassistant/components/met/weather.py +++ b/homeassistant/components/met/weather.py @@ -3,14 +3,23 @@ import logging import voluptuous as vol -from homeassistant.components.weather import PLATFORM_SCHEMA, WeatherEntity +from homeassistant.components.weather import ( + ATTR_FORECAST_CONDITION, + ATTR_WEATHER_HUMIDITY, + ATTR_WEATHER_PRESSURE, + ATTR_WEATHER_TEMPERATURE, + ATTR_WEATHER_WIND_BEARING, + ATTR_WEATHER_WIND_SPEED, + PLATFORM_SCHEMA, + WeatherEntity, +) from homeassistant.config_entries import SOURCE_IMPORT from homeassistant.const import ( CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, - LENGTH_METERS, + LENGTH_KILOMETERS, LENGTH_MILES, PRESSURE_HPA, PRESSURE_INHG, @@ -21,7 +30,7 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.util.distance import convert as convert_distance from homeassistant.util.pressure import convert as convert_pressure -from .const import CONF_TRACK_HOME, DOMAIN +from .const import ATTR_MAP, CONDITIONS_MAP, CONF_TRACK_HOME, DOMAIN, FORECAST_MAP _LOGGER = logging.getLogger(__name__) @@ -78,6 +87,14 @@ async def async_setup_entry(hass, config_entry, async_add_entities): ) +def format_condition(condition: str) -> str: + """Return condition from dict CONDITIONS_MAP.""" + for key, value in CONDITIONS_MAP.items(): + if condition in value: + return key + return condition + + class MetWeather(CoordinatorEntity, WeatherEntity): """Implementation of a Met.no weather condition.""" @@ -118,12 +135,15 @@ class MetWeather(CoordinatorEntity, WeatherEntity): @property def condition(self): """Return the current condition.""" - return self.coordinator.data.current_weather_data.get("condition") + condition = self.coordinator.data.current_weather_data.get("condition") + return format_condition(condition) @property def temperature(self): """Return the temperature.""" - return self.coordinator.data.current_weather_data.get("temperature") + return self.coordinator.data.current_weather_data.get( + ATTR_MAP[ATTR_WEATHER_TEMPERATURE] + ) @property def temperature_unit(self): @@ -133,7 +153,9 @@ class MetWeather(CoordinatorEntity, WeatherEntity): @property def pressure(self): """Return the pressure.""" - pressure_hpa = self.coordinator.data.current_weather_data.get("pressure") + pressure_hpa = self.coordinator.data.current_weather_data.get( + ATTR_MAP[ATTR_WEATHER_PRESSURE] + ) if self._is_metric or pressure_hpa is None: return pressure_hpa @@ -142,23 +164,28 @@ class MetWeather(CoordinatorEntity, WeatherEntity): @property def humidity(self): """Return the humidity.""" - return self.coordinator.data.current_weather_data.get("humidity") + return self.coordinator.data.current_weather_data.get( + ATTR_MAP[ATTR_WEATHER_HUMIDITY] + ) @property def wind_speed(self): """Return the wind speed.""" - speed_m_s = self.coordinator.data.current_weather_data.get("wind_speed") - if self._is_metric or speed_m_s is None: - return speed_m_s + speed_km_h = self.coordinator.data.current_weather_data.get( + ATTR_MAP[ATTR_WEATHER_WIND_SPEED] + ) + if self._is_metric or speed_km_h is None: + return speed_km_h - speed_mi_s = convert_distance(speed_m_s, LENGTH_METERS, LENGTH_MILES) - speed_mi_h = speed_mi_s / 3600.0 + speed_mi_h = convert_distance(speed_km_h, LENGTH_KILOMETERS, LENGTH_MILES) return int(round(speed_mi_h)) @property def wind_bearing(self): """Return the wind direction.""" - return self.coordinator.data.current_weather_data.get("wind_bearing") + return self.coordinator.data.current_weather_data.get( + ATTR_MAP[ATTR_WEATHER_WIND_BEARING] + ) @property def attribution(self): @@ -169,5 +196,16 @@ class MetWeather(CoordinatorEntity, WeatherEntity): def forecast(self): """Return the forecast array.""" if self._hourly: - return self.coordinator.data.hourly_forecast - return self.coordinator.data.daily_forecast + met_forecast = self.coordinator.data.hourly_forecast + else: + met_forecast = self.coordinator.data.daily_forecast + ha_forecast = [] + for met_item in met_forecast: + ha_item = { + k: met_item[v] for k, v in FORECAST_MAP.items() if met_item.get(v) + } + ha_item[ATTR_FORECAST_CONDITION] = format_condition( + ha_item[ATTR_FORECAST_CONDITION] + ) + ha_forecast.append(ha_item) + return ha_forecast diff --git a/homeassistant/components/norway_air/manifest.json b/homeassistant/components/norway_air/manifest.json index 96ff39bb6dd..193d96e2a18 100644 --- a/homeassistant/components/norway_air/manifest.json +++ b/homeassistant/components/norway_air/manifest.json @@ -2,6 +2,6 @@ "domain": "norway_air", "name": "Om Luftkvalitet i Norge (Norway Air)", "documentation": "https://www.home-assistant.io/integrations/norway_air", - "requirements": ["pyMetno==0.7.1"], + "requirements": ["pyMetno==0.8.1"], "codeowners": [] } diff --git a/homeassistant/components/weather/__init__.py b/homeassistant/components/weather/__init__.py index 5a6fcc2d80b..8ddcf052e1f 100644 --- a/homeassistant/components/weather/__init__.py +++ b/homeassistant/components/weather/__init__.py @@ -16,6 +16,21 @@ from homeassistant.helpers.temperature import display_temp as show_temp _LOGGER = logging.getLogger(__name__) ATTR_CONDITION_CLASS = "condition_class" +ATTR_CONDITION_CLEAR_NIGHT = "clear-night" +ATTR_CONDITION_CLOUDY = "cloudy" +ATTR_CONDITION_EXCEPTIONAL = "exceptional" +ATTR_CONDITION_FOG = "fog" +ATTR_CONDITION_HAIL = "hail" +ATTR_CONDITION_LIGHTNING = "lightning" +ATTR_CONDITION_LIGHTNING_RAINY = "lightning-rainy" +ATTR_CONDITION_PARTLYCLOUDY = "partlycloudy" +ATTR_CONDITION_POURING = "pouring" +ATTR_CONDITION_RAINY = "rainy" +ATTR_CONDITION_SNOWY = "snowy" +ATTR_CONDITION_SNOWY_RAINY = "snowy-rainy" +ATTR_CONDITION_SUNNY = "sunny" +ATTR_CONDITION_WINDY = "windy" +ATTR_CONDITION_WINDY_VARIANT = "windy-variant" ATTR_FORECAST = "forecast" ATTR_FORECAST_CONDITION = "condition" ATTR_FORECAST_PRECIPITATION = "precipitation" diff --git a/requirements_all.txt b/requirements_all.txt index e6a49977d10..2e90608aada 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1186,7 +1186,7 @@ pyHS100==0.3.5.1 # homeassistant.components.met # homeassistant.components.norway_air -pyMetno==0.7.1 +pyMetno==0.8.1 # homeassistant.components.rfxtrx pyRFXtrx==0.25 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c0354d60ade..0870058a2c4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -577,7 +577,7 @@ pyHS100==0.3.5.1 # homeassistant.components.met # homeassistant.components.norway_air -pyMetno==0.7.1 +pyMetno==0.8.1 # homeassistant.components.rfxtrx pyRFXtrx==0.25