Fix wind speed SMHI (#72999)

This commit is contained in:
G Johansson 2022-06-28 01:50:06 +02:00 committed by GitHub
parent b2c84a4c4a
commit 2f0fe0df82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 88 additions and 26 deletions

View File

@ -2,9 +2,10 @@
from __future__ import annotations
import asyncio
from collections.abc import Mapping
from datetime import datetime, timedelta
import logging
from typing import Final
from typing import Any, Final
import aiohttp
import async_timeout
@ -27,10 +28,14 @@ from homeassistant.components.weather import (
ATTR_CONDITION_WINDY,
ATTR_CONDITION_WINDY_VARIANT,
ATTR_FORECAST_CONDITION,
ATTR_FORECAST_PRECIPITATION,
ATTR_FORECAST_TEMP,
ATTR_FORECAST_TEMP_LOW,
ATTR_FORECAST_NATIVE_PRECIPITATION,
ATTR_FORECAST_NATIVE_PRESSURE,
ATTR_FORECAST_NATIVE_TEMP,
ATTR_FORECAST_NATIVE_TEMP_LOW,
ATTR_FORECAST_NATIVE_WIND_SPEED,
ATTR_FORECAST_TIME,
ATTR_FORECAST_WIND_BEARING,
ROUNDING_PRECISION,
Forecast,
WeatherEntity,
)
@ -41,6 +46,8 @@ from homeassistant.const import (
CONF_NAME,
LENGTH_KILOMETERS,
LENGTH_MILLIMETERS,
PRESSURE_HPA,
SPEED_METERS_PER_SECOND,
TEMP_CELSIUS,
)
from homeassistant.core import HomeAssistant
@ -49,7 +56,7 @@ from homeassistant.helpers.device_registry import DeviceEntryType
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_call_later
from homeassistant.util import Throttle, slugify
from homeassistant.util import Throttle, slugify, speed as speed_util
from .const import (
ATTR_SMHI_CLOUDINESS,
@ -112,9 +119,11 @@ class SmhiWeather(WeatherEntity):
"""Representation of a weather entity."""
_attr_attribution = "Swedish weather institute (SMHI)"
_attr_temperature_unit = TEMP_CELSIUS
_attr_visibility_unit = LENGTH_KILOMETERS
_attr_precipitation_unit = LENGTH_MILLIMETERS
_attr_native_temperature_unit = TEMP_CELSIUS
_attr_native_visibility_unit = LENGTH_KILOMETERS
_attr_native_precipitation_unit = LENGTH_MILLIMETERS
_attr_native_wind_speed_unit = SPEED_METERS_PER_SECOND
_attr_native_pressure_unit = PRESSURE_HPA
def __init__(
self,
@ -139,7 +148,23 @@ class SmhiWeather(WeatherEntity):
configuration_url="http://opendata.smhi.se/apidocs/metfcst/parameters.html",
)
self._attr_condition = None
self._attr_temperature = None
self._attr_native_temperature = None
@property
def extra_state_attributes(self) -> Mapping[str, Any] | None:
"""Return additional attributes."""
if self._forecasts:
wind_gust = speed_util.convert(
self._forecasts[0].wind_gust,
SPEED_METERS_PER_SECOND,
self._wind_speed_unit,
)
return {
ATTR_SMHI_CLOUDINESS: self._forecasts[0].cloudiness,
ATTR_SMHI_WIND_GUST_SPEED: round(wind_gust, ROUNDING_PRECISION),
ATTR_SMHI_THUNDER_PROBABILITY: self._forecasts[0].thunder,
}
return None
@Throttle(MIN_TIME_BETWEEN_UPDATES)
async def async_update(self) -> None:
@ -156,13 +181,12 @@ class SmhiWeather(WeatherEntity):
return
if self._forecasts:
self._attr_temperature = self._forecasts[0].temperature
self._attr_native_temperature = self._forecasts[0].temperature
self._attr_humidity = self._forecasts[0].humidity
# Convert from m/s to km/h
self._attr_wind_speed = round(self._forecasts[0].wind_speed * 18 / 5)
self._attr_native_wind_speed = self._forecasts[0].wind_speed
self._attr_wind_bearing = self._forecasts[0].wind_direction
self._attr_visibility = self._forecasts[0].horizontal_visibility
self._attr_pressure = self._forecasts[0].pressure
self._attr_native_visibility = self._forecasts[0].horizontal_visibility
self._attr_native_pressure = self._forecasts[0].pressure
self._attr_condition = next(
(
k
@ -171,12 +195,6 @@ class SmhiWeather(WeatherEntity):
),
None,
)
self._attr_extra_state_attributes = {
ATTR_SMHI_CLOUDINESS: self._forecasts[0].cloudiness,
# Convert from m/s to km/h
ATTR_SMHI_WIND_GUST_SPEED: round(self._forecasts[0].wind_gust * 18 / 5),
ATTR_SMHI_THUNDER_PROBABILITY: self._forecasts[0].thunder,
}
async def retry_update(self, _: datetime) -> None:
"""Retry refresh weather forecast."""
@ -200,10 +218,13 @@ class SmhiWeather(WeatherEntity):
data.append(
{
ATTR_FORECAST_TIME: forecast.valid_time.isoformat(),
ATTR_FORECAST_TEMP: forecast.temperature_max,
ATTR_FORECAST_TEMP_LOW: forecast.temperature_min,
ATTR_FORECAST_PRECIPITATION: round(forecast.total_precipitation, 1),
ATTR_FORECAST_NATIVE_TEMP: forecast.temperature_max,
ATTR_FORECAST_NATIVE_TEMP_LOW: forecast.temperature_min,
ATTR_FORECAST_NATIVE_PRECIPITATION: forecast.total_precipitation,
ATTR_FORECAST_CONDITION: condition,
ATTR_FORECAST_NATIVE_PRESSURE: forecast.pressure,
ATTR_FORECAST_WIND_BEARING: forecast.wind_direction,
ATTR_FORECAST_NATIVE_WIND_SPEED: forecast.wind_speed,
}
)

View File

@ -16,18 +16,24 @@ from homeassistant.components.weather import (
ATTR_FORECAST,
ATTR_FORECAST_CONDITION,
ATTR_FORECAST_PRECIPITATION,
ATTR_FORECAST_PRESSURE,
ATTR_FORECAST_TEMP,
ATTR_FORECAST_TEMP_LOW,
ATTR_FORECAST_TIME,
ATTR_FORECAST_WIND_BEARING,
ATTR_FORECAST_WIND_SPEED,
ATTR_WEATHER_HUMIDITY,
ATTR_WEATHER_PRESSURE,
ATTR_WEATHER_TEMPERATURE,
ATTR_WEATHER_VISIBILITY,
ATTR_WEATHER_WIND_BEARING,
ATTR_WEATHER_WIND_SPEED,
ATTR_WEATHER_WIND_SPEED_UNIT,
DOMAIN as WEATHER_DOMAIN,
)
from homeassistant.const import ATTR_ATTRIBUTION, STATE_UNKNOWN
from homeassistant.const import ATTR_ATTRIBUTION, SPEED_METERS_PER_SECOND, STATE_UNKNOWN
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.util.dt import utcnow
from . import ENTITY_ID, TEST_CONFIG
@ -58,13 +64,13 @@ async def test_setup_hass(
assert state.state == "sunny"
assert state.attributes[ATTR_SMHI_CLOUDINESS] == 50
assert state.attributes[ATTR_SMHI_THUNDER_PROBABILITY] == 33
assert state.attributes[ATTR_SMHI_WIND_GUST_SPEED] == 17
assert state.attributes[ATTR_SMHI_WIND_GUST_SPEED] == 16.92
assert state.attributes[ATTR_ATTRIBUTION].find("SMHI") >= 0
assert state.attributes[ATTR_WEATHER_HUMIDITY] == 55
assert state.attributes[ATTR_WEATHER_PRESSURE] == 1024
assert state.attributes[ATTR_WEATHER_TEMPERATURE] == 17
assert state.attributes[ATTR_WEATHER_VISIBILITY] == 50
assert state.attributes[ATTR_WEATHER_WIND_SPEED] == 7
assert state.attributes[ATTR_WEATHER_WIND_SPEED] == 6.84
assert state.attributes[ATTR_WEATHER_WIND_BEARING] == 134
assert len(state.attributes["forecast"]) == 4
@ -74,6 +80,9 @@ async def test_setup_hass(
assert forecast[ATTR_FORECAST_TEMP_LOW] == 6
assert forecast[ATTR_FORECAST_PRECIPITATION] == 0
assert forecast[ATTR_FORECAST_CONDITION] == "partlycloudy"
assert forecast[ATTR_FORECAST_PRESSURE] == 1026
assert forecast[ATTR_FORECAST_WIND_BEARING] == 203
assert forecast[ATTR_FORECAST_WIND_SPEED] == 6.12
async def test_properties_no_data(hass: HomeAssistant) -> None:
@ -305,3 +314,35 @@ def test_condition_class():
assert get_condition(23) == "snowy-rainy"
# 24. Heavy sleet
assert get_condition(24) == "snowy-rainy"
async def test_custom_speed_unit(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, api_response: str
) -> None:
"""Test Wind Gust speed with custom unit."""
uri = APIURL_TEMPLATE.format(TEST_CONFIG["longitude"], TEST_CONFIG["latitude"])
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain="smhi", data=TEST_CONFIG)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state
assert state.name == "test"
assert state.attributes[ATTR_SMHI_WIND_GUST_SPEED] == 16.92
entity_reg = er.async_get(hass)
entity_reg.async_update_entity_options(
state.entity_id,
WEATHER_DOMAIN,
{ATTR_WEATHER_WIND_SPEED_UNIT: SPEED_METERS_PER_SECOND},
)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state.attributes[ATTR_SMHI_WIND_GUST_SPEED] == 4.7