mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Fix wind speed SMHI (#72999)
This commit is contained in:
parent
b2c84a4c4a
commit
2f0fe0df82
@ -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,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user