From 47048e4df4a2e1128a0c5258f993a1e26416c413 Mon Sep 17 00:00:00 2001
From: Erik Montnemery <erik@montnemery.com>
Date: Wed, 6 Jul 2022 16:22:45 +0200
Subject: [PATCH] Migrate aemet weather to native_* (#74494)

---
 homeassistant/components/aemet/const.py       | 48 ++++++-------
 homeassistant/components/aemet/sensor.py      | 20 +++---
 homeassistant/components/aemet/weather.py     | 69 ++++++++++++++++---
 .../aemet/weather_update_coordinator.py       | 46 ++++++-------
 4 files changed, 114 insertions(+), 69 deletions(-)

diff --git a/homeassistant/components/aemet/const.py b/homeassistant/components/aemet/const.py
index 4be90011f5a..645c1ad0ea2 100644
--- a/homeassistant/components/aemet/const.py
+++ b/homeassistant/components/aemet/const.py
@@ -17,14 +17,6 @@ from homeassistant.components.weather import (
     ATTR_CONDITION_RAINY,
     ATTR_CONDITION_SNOWY,
     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,
 )
 from homeassistant.const import (
     DEGREE,
@@ -45,8 +37,16 @@ ENTRY_NAME = "name"
 ENTRY_WEATHER_COORDINATOR = "weather_coordinator"
 
 ATTR_API_CONDITION = "condition"
+ATTR_API_FORECAST_CONDITION = "condition"
 ATTR_API_FORECAST_DAILY = "forecast-daily"
 ATTR_API_FORECAST_HOURLY = "forecast-hourly"
+ATTR_API_FORECAST_PRECIPITATION = "precipitation"
+ATTR_API_FORECAST_PRECIPITATION_PROBABILITY = "precipitation_probability"
+ATTR_API_FORECAST_TEMP = "temperature"
+ATTR_API_FORECAST_TEMP_LOW = "templow"
+ATTR_API_FORECAST_TIME = "datetime"
+ATTR_API_FORECAST_WIND_BEARING = "wind_bearing"
+ATTR_API_FORECAST_WIND_SPEED = "wind_speed"
 ATTR_API_HUMIDITY = "humidity"
 ATTR_API_PRESSURE = "pressure"
 ATTR_API_RAIN = "rain"
@@ -158,14 +158,14 @@ CONDITIONS_MAP = {
 }
 
 FORECAST_MONITORED_CONDITIONS = [
-    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_API_FORECAST_CONDITION,
+    ATTR_API_FORECAST_PRECIPITATION,
+    ATTR_API_FORECAST_PRECIPITATION_PROBABILITY,
+    ATTR_API_FORECAST_TEMP,
+    ATTR_API_FORECAST_TEMP_LOW,
+    ATTR_API_FORECAST_TIME,
+    ATTR_API_FORECAST_WIND_BEARING,
+    ATTR_API_FORECAST_WIND_SPEED,
 ]
 MONITORED_CONDITIONS = [
     ATTR_API_CONDITION,
@@ -202,43 +202,43 @@ FORECAST_MODE_ATTR_API = {
 
 FORECAST_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
     SensorEntityDescription(
-        key=ATTR_FORECAST_CONDITION,
+        key=ATTR_API_FORECAST_CONDITION,
         name="Condition",
     ),
     SensorEntityDescription(
-        key=ATTR_FORECAST_PRECIPITATION,
+        key=ATTR_API_FORECAST_PRECIPITATION,
         name="Precipitation",
         native_unit_of_measurement=PRECIPITATION_MILLIMETERS_PER_HOUR,
     ),
     SensorEntityDescription(
-        key=ATTR_FORECAST_PRECIPITATION_PROBABILITY,
+        key=ATTR_API_FORECAST_PRECIPITATION_PROBABILITY,
         name="Precipitation probability",
         native_unit_of_measurement=PERCENTAGE,
     ),
     SensorEntityDescription(
-        key=ATTR_FORECAST_TEMP,
+        key=ATTR_API_FORECAST_TEMP,
         name="Temperature",
         native_unit_of_measurement=TEMP_CELSIUS,
         device_class=SensorDeviceClass.TEMPERATURE,
     ),
     SensorEntityDescription(
-        key=ATTR_FORECAST_TEMP_LOW,
+        key=ATTR_API_FORECAST_TEMP_LOW,
         name="Temperature Low",
         native_unit_of_measurement=TEMP_CELSIUS,
         device_class=SensorDeviceClass.TEMPERATURE,
     ),
     SensorEntityDescription(
-        key=ATTR_FORECAST_TIME,
+        key=ATTR_API_FORECAST_TIME,
         name="Time",
         device_class=SensorDeviceClass.TIMESTAMP,
     ),
     SensorEntityDescription(
-        key=ATTR_FORECAST_WIND_BEARING,
+        key=ATTR_API_FORECAST_WIND_BEARING,
         name="Wind bearing",
         native_unit_of_measurement=DEGREE,
     ),
     SensorEntityDescription(
-        key=ATTR_FORECAST_WIND_SPEED,
+        key=ATTR_API_FORECAST_WIND_SPEED,
         name="Wind speed",
         native_unit_of_measurement=SPEED_KILOMETERS_PER_HOUR,
     ),
diff --git a/homeassistant/components/aemet/sensor.py b/homeassistant/components/aemet/sensor.py
index f98e3fff49e..e34583148e1 100644
--- a/homeassistant/components/aemet/sensor.py
+++ b/homeassistant/components/aemet/sensor.py
@@ -10,7 +10,7 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
 from homeassistant.util import dt as dt_util
 
 from .const import (
-    ATTR_FORECAST_TIME,
+    ATTR_API_FORECAST_TIME,
     ATTRIBUTION,
     DOMAIN,
     ENTRY_NAME,
@@ -45,17 +45,13 @@ async def async_setup_entry(
     entities.extend(
         [
             AemetForecastSensor(
-                name_prefix,
-                unique_id_prefix,
+                f"{domain_data[ENTRY_NAME]} {mode} Forecast",
+                f"{unique_id}-forecast-{mode}",
                 weather_coordinator,
                 mode,
                 description,
             )
             for mode in FORECAST_MODES
-            if (
-                (name_prefix := f"{domain_data[ENTRY_NAME]} {mode} Forecast")
-                and (unique_id_prefix := f"{unique_id}-forecast-{mode}")
-            )
             for description in FORECAST_SENSOR_TYPES
             if description.key in FORECAST_MONITORED_CONDITIONS
         ]
@@ -89,14 +85,14 @@ class AemetSensor(AbstractAemetSensor):
     def __init__(
         self,
         name,
-        unique_id,
+        unique_id_prefix,
         weather_coordinator: WeatherUpdateCoordinator,
         description: SensorEntityDescription,
     ):
         """Initialize the sensor."""
         super().__init__(
             name=name,
-            unique_id=f"{unique_id}-{description.key}",
+            unique_id=f"{unique_id_prefix}-{description.key}",
             coordinator=weather_coordinator,
             description=description,
         )
@@ -113,7 +109,7 @@ class AemetForecastSensor(AbstractAemetSensor):
     def __init__(
         self,
         name,
-        unique_id,
+        unique_id_prefix,
         weather_coordinator: WeatherUpdateCoordinator,
         forecast_mode,
         description: SensorEntityDescription,
@@ -121,7 +117,7 @@ class AemetForecastSensor(AbstractAemetSensor):
         """Initialize the sensor."""
         super().__init__(
             name=name,
-            unique_id=f"{unique_id}-{description.key}",
+            unique_id=f"{unique_id_prefix}-{description.key}",
             coordinator=weather_coordinator,
             description=description,
         )
@@ -139,6 +135,6 @@ class AemetForecastSensor(AbstractAemetSensor):
         )
         if forecasts:
             forecast = forecasts[0].get(self.entity_description.key)
-            if self.entity_description.key == ATTR_FORECAST_TIME:
+            if self.entity_description.key == ATTR_API_FORECAST_TIME:
                 forecast = dt_util.parse_datetime(forecast)
         return forecast
diff --git a/homeassistant/components/aemet/weather.py b/homeassistant/components/aemet/weather.py
index d05442b621e..a7ff3630e78 100644
--- a/homeassistant/components/aemet/weather.py
+++ b/homeassistant/components/aemet/weather.py
@@ -1,13 +1,36 @@
 """Support for the AEMET OpenData service."""
-from homeassistant.components.weather import WeatherEntity
+from homeassistant.components.weather import (
+    ATTR_FORECAST_CONDITION,
+    ATTR_FORECAST_NATIVE_PRECIPITATION,
+    ATTR_FORECAST_NATIVE_TEMP,
+    ATTR_FORECAST_NATIVE_TEMP_LOW,
+    ATTR_FORECAST_NATIVE_WIND_SPEED,
+    ATTR_FORECAST_PRECIPITATION_PROBABILITY,
+    ATTR_FORECAST_TIME,
+    ATTR_FORECAST_WIND_BEARING,
+    WeatherEntity,
+)
 from homeassistant.config_entries import ConfigEntry
-from homeassistant.const import PRESSURE_HPA, SPEED_KILOMETERS_PER_HOUR, TEMP_CELSIUS
+from homeassistant.const import (
+    LENGTH_MILLIMETERS,
+    PRESSURE_HPA,
+    SPEED_KILOMETERS_PER_HOUR,
+    TEMP_CELSIUS,
+)
 from homeassistant.core import HomeAssistant
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
 from homeassistant.helpers.update_coordinator import CoordinatorEntity
 
 from .const import (
     ATTR_API_CONDITION,
+    ATTR_API_FORECAST_CONDITION,
+    ATTR_API_FORECAST_PRECIPITATION,
+    ATTR_API_FORECAST_PRECIPITATION_PROBABILITY,
+    ATTR_API_FORECAST_TEMP,
+    ATTR_API_FORECAST_TEMP_LOW,
+    ATTR_API_FORECAST_TIME,
+    ATTR_API_FORECAST_WIND_BEARING,
+    ATTR_API_FORECAST_WIND_SPEED,
     ATTR_API_HUMIDITY,
     ATTR_API_PRESSURE,
     ATTR_API_TEMPERATURE,
@@ -19,10 +42,32 @@ from .const import (
     ENTRY_WEATHER_COORDINATOR,
     FORECAST_MODE_ATTR_API,
     FORECAST_MODE_DAILY,
+    FORECAST_MODE_HOURLY,
     FORECAST_MODES,
 )
 from .weather_update_coordinator import WeatherUpdateCoordinator
 
+FORECAST_MAP = {
+    FORECAST_MODE_DAILY: {
+        ATTR_API_FORECAST_CONDITION: ATTR_FORECAST_CONDITION,
+        ATTR_API_FORECAST_PRECIPITATION_PROBABILITY: ATTR_FORECAST_PRECIPITATION_PROBABILITY,
+        ATTR_API_FORECAST_TEMP_LOW: ATTR_FORECAST_NATIVE_TEMP_LOW,
+        ATTR_API_FORECAST_TEMP: ATTR_FORECAST_NATIVE_TEMP,
+        ATTR_API_FORECAST_TIME: ATTR_FORECAST_TIME,
+        ATTR_API_FORECAST_WIND_BEARING: ATTR_FORECAST_WIND_BEARING,
+        ATTR_API_FORECAST_WIND_SPEED: ATTR_FORECAST_NATIVE_WIND_SPEED,
+    },
+    FORECAST_MODE_HOURLY: {
+        ATTR_API_FORECAST_CONDITION: ATTR_FORECAST_CONDITION,
+        ATTR_API_FORECAST_PRECIPITATION_PROBABILITY: ATTR_FORECAST_PRECIPITATION_PROBABILITY,
+        ATTR_API_FORECAST_PRECIPITATION: ATTR_FORECAST_NATIVE_PRECIPITATION,
+        ATTR_API_FORECAST_TEMP: ATTR_FORECAST_NATIVE_TEMP,
+        ATTR_API_FORECAST_TIME: ATTR_FORECAST_TIME,
+        ATTR_API_FORECAST_WIND_BEARING: ATTR_FORECAST_WIND_BEARING,
+        ATTR_API_FORECAST_WIND_SPEED: ATTR_FORECAST_NATIVE_WIND_SPEED,
+    },
+}
+
 
 async def async_setup_entry(
     hass: HomeAssistant,
@@ -47,9 +92,10 @@ class AemetWeather(CoordinatorEntity[WeatherUpdateCoordinator], WeatherEntity):
     """Implementation of an AEMET OpenData sensor."""
 
     _attr_attribution = ATTRIBUTION
-    _attr_temperature_unit = TEMP_CELSIUS
-    _attr_pressure_unit = PRESSURE_HPA
-    _attr_wind_speed_unit = SPEED_KILOMETERS_PER_HOUR
+    _attr_native_precipitation_unit = LENGTH_MILLIMETERS
+    _attr_native_pressure_unit = PRESSURE_HPA
+    _attr_native_temperature_unit = TEMP_CELSIUS
+    _attr_native_wind_speed_unit = SPEED_KILOMETERS_PER_HOUR
 
     def __init__(
         self,
@@ -75,7 +121,12 @@ class AemetWeather(CoordinatorEntity[WeatherUpdateCoordinator], WeatherEntity):
     @property
     def forecast(self):
         """Return the forecast array."""
-        return self.coordinator.data[FORECAST_MODE_ATTR_API[self._forecast_mode]]
+        forecasts = self.coordinator.data[FORECAST_MODE_ATTR_API[self._forecast_mode]]
+        forecast_map = FORECAST_MAP[self._forecast_mode]
+        return [
+            {ha_key: forecast[api_key] for api_key, ha_key in forecast_map.items()}
+            for forecast in forecasts
+        ]
 
     @property
     def humidity(self):
@@ -83,12 +134,12 @@ class AemetWeather(CoordinatorEntity[WeatherUpdateCoordinator], WeatherEntity):
         return self.coordinator.data[ATTR_API_HUMIDITY]
 
     @property
-    def pressure(self):
+    def native_pressure(self):
         """Return the pressure."""
         return self.coordinator.data[ATTR_API_PRESSURE]
 
     @property
-    def temperature(self):
+    def native_temperature(self):
         """Return the temperature."""
         return self.coordinator.data[ATTR_API_TEMPERATURE]
 
@@ -98,6 +149,6 @@ class AemetWeather(CoordinatorEntity[WeatherUpdateCoordinator], WeatherEntity):
         return self.coordinator.data[ATTR_API_WIND_BEARING]
 
     @property
-    def wind_speed(self):
+    def native_wind_speed(self):
         """Return the wind speed."""
         return self.coordinator.data[ATTR_API_WIND_SPEED]
diff --git a/homeassistant/components/aemet/weather_update_coordinator.py b/homeassistant/components/aemet/weather_update_coordinator.py
index c86465ea8f1..1c64206891c 100644
--- a/homeassistant/components/aemet/weather_update_coordinator.py
+++ b/homeassistant/components/aemet/weather_update_coordinator.py
@@ -42,23 +42,21 @@ from aemet_opendata.helpers import (
 )
 import async_timeout
 
-from homeassistant.components.weather import (
-    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,
-)
 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
 from homeassistant.util import dt as dt_util
 
 from .const import (
     ATTR_API_CONDITION,
+    ATTR_API_FORECAST_CONDITION,
     ATTR_API_FORECAST_DAILY,
     ATTR_API_FORECAST_HOURLY,
+    ATTR_API_FORECAST_PRECIPITATION,
+    ATTR_API_FORECAST_PRECIPITATION_PROBABILITY,
+    ATTR_API_FORECAST_TEMP,
+    ATTR_API_FORECAST_TEMP_LOW,
+    ATTR_API_FORECAST_TIME,
+    ATTR_API_FORECAST_WIND_BEARING,
+    ATTR_API_FORECAST_WIND_SPEED,
     ATTR_API_HUMIDITY,
     ATTR_API_PRESSURE,
     ATTR_API_RAIN,
@@ -402,15 +400,15 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
             return None
 
         return {
-            ATTR_FORECAST_CONDITION: condition,
-            ATTR_FORECAST_PRECIPITATION_PROBABILITY: self._get_precipitation_prob_day(
+            ATTR_API_FORECAST_CONDITION: condition,
+            ATTR_API_FORECAST_PRECIPITATION_PROBABILITY: self._get_precipitation_prob_day(
                 day
             ),
-            ATTR_FORECAST_TEMP: self._get_temperature_day(day),
-            ATTR_FORECAST_TEMP_LOW: self._get_temperature_low_day(day),
-            ATTR_FORECAST_TIME: dt_util.as_utc(date).isoformat(),
-            ATTR_FORECAST_WIND_SPEED: self._get_wind_speed_day(day),
-            ATTR_FORECAST_WIND_BEARING: self._get_wind_bearing_day(day),
+            ATTR_API_FORECAST_TEMP: self._get_temperature_day(day),
+            ATTR_API_FORECAST_TEMP_LOW: self._get_temperature_low_day(day),
+            ATTR_API_FORECAST_TIME: dt_util.as_utc(date).isoformat(),
+            ATTR_API_FORECAST_WIND_SPEED: self._get_wind_speed_day(day),
+            ATTR_API_FORECAST_WIND_BEARING: self._get_wind_bearing_day(day),
         }
 
     def _convert_forecast_hour(self, date, day, hour):
@@ -420,15 +418,15 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
         forecast_dt = date.replace(hour=hour, minute=0, second=0)
 
         return {
-            ATTR_FORECAST_CONDITION: condition,
-            ATTR_FORECAST_PRECIPITATION: self._calc_precipitation(day, hour),
-            ATTR_FORECAST_PRECIPITATION_PROBABILITY: self._calc_precipitation_prob(
+            ATTR_API_FORECAST_CONDITION: condition,
+            ATTR_API_FORECAST_PRECIPITATION: self._calc_precipitation(day, hour),
+            ATTR_API_FORECAST_PRECIPITATION_PROBABILITY: self._calc_precipitation_prob(
                 day, hour
             ),
-            ATTR_FORECAST_TEMP: self._get_temperature(day, hour),
-            ATTR_FORECAST_TIME: dt_util.as_utc(forecast_dt).isoformat(),
-            ATTR_FORECAST_WIND_SPEED: self._get_wind_speed(day, hour),
-            ATTR_FORECAST_WIND_BEARING: self._get_wind_bearing(day, hour),
+            ATTR_API_FORECAST_TEMP: self._get_temperature(day, hour),
+            ATTR_API_FORECAST_TIME: dt_util.as_utc(forecast_dt).isoformat(),
+            ATTR_API_FORECAST_WIND_SPEED: self._get_wind_speed(day, hour),
+            ATTR_API_FORECAST_WIND_BEARING: self._get_wind_bearing(day, hour),
         }
 
     def _calc_precipitation(self, day, hour):