Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions homeassistant/components/openweathermap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
from dataclasses import dataclass
import logging

from pyopenweathermap import create_owm_client

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, CONF_LANGUAGE, CONF_MODE
from homeassistant.core import HomeAssistant

from .const import CONFIG_FLOW_VERSION, DEFAULT_OWM_MODE, OWM_MODES, PLATFORMS
from .coordinator import OWMUpdateCoordinator, get_owm_update_coordinator
from .repairs import async_create_issue, async_delete_issue
from .utils import build_data_and_options
from .utils import build_data_and_options, get_owm_client

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -40,7 +38,7 @@ async def async_setup_entry(
else:
async_delete_issue(hass, entry.entry_id)

owm_client = create_owm_client(api_key, mode, lang=language)
owm_client = get_owm_client(api_key, mode, language)
owm_coordinator = get_owm_update_coordinator(mode)(hass, entry, owm_client)

await owm_coordinator.async_config_entry_first_refresh()
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/openweathermap/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@
OWM_MODE_FREE_CURRENT = "current"
OWM_MODE_FREE_FORECAST = "forecast"
OWM_MODE_V30 = "v3.0"
OWM_MODE_V40 = "v4.0"
OWM_MODE_AIRPOLLUTION = "air_pollution"
OWM_MODES = [
OWM_MODE_V30,
OWM_MODE_V40,
OWM_MODE_FREE_CURRENT,
OWM_MODE_FREE_FORECAST,
OWM_MODE_AIRPOLLUTION,
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/openweathermap/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
OWM_MODE_FREE_CURRENT,
OWM_MODE_FREE_FORECAST,
OWM_MODE_V30,
OWM_MODE_V40,
WEATHER_CODE_SUNNY_OR_CLEAR_NIGHT,
)

Expand Down Expand Up @@ -309,6 +310,7 @@ def get_owm_update_coordinator(mode: str) -> type[OWMUpdateCoordinator]:
"""Create coordinator with a factory."""
coordinators = {
OWM_MODE_V30: WeatherUpdateCoordinator,
OWM_MODE_V40: WeatherUpdateCoordinator,
OWM_MODE_FREE_CURRENT: WeatherUpdateCoordinator,
OWM_MODE_FREE_FORECAST: WeatherUpdateCoordinator,
OWM_MODE_AIRPOLLUTION: AirPollutionUpdateCoordinator,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/openweathermap/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
},
"exceptions": {
"service_minute_forecast_mode": {
"message": "Minute forecast is available only when {name} mode is set to v3.0"
"message": "Minute forecast is available only when {name} mode is set to v3.0 or v4.0"
}
},
"issues": {
Expand Down
26 changes: 24 additions & 2 deletions homeassistant/components/openweathermap/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,42 @@
from typing import Any

from pyopenweathermap import RequestError, create_owm_client
from pyopenweathermap.client.onecall_client import OWMOneCallClient

from homeassistant.const import CONF_LANGUAGE, CONF_MODE

from .const import DEFAULT_LANGUAGE, DEFAULT_OWM_MODE
from .const import DEFAULT_LANGUAGE, DEFAULT_OWM_MODE, OWM_MODE_V40

OPTION_DEFAULTS = {CONF_LANGUAGE: DEFAULT_LANGUAGE, CONF_MODE: DEFAULT_OWM_MODE}


class OWMOneCallClientV4(OWMOneCallClient):
"""OWM client for One Call API 4.0."""

def _get_url(self, lat: float, lon: float) -> str:
Comment on lines +15 to +18
return (
"https://api.openweathermap.org/data/4.0/onecall?"
Comment on lines +15 to +20
f"lat={lat}&"
f"lon={lon}&"
f"appid={self.api_key}&"
f"units={self.units}&"
f"lang={self.lang}"
)


def get_owm_client(api_key: str, mode: str, language: str = DEFAULT_LANGUAGE) -> Any:
"""Get the OWM client."""
if mode == OWM_MODE_V40:
return OWMOneCallClientV4(api_key, mode, lang=language)
Comment on lines +31 to +32
Comment on lines +31 to +32
return create_owm_client(api_key, mode, lang=language)


async def validate_api_key(api_key, mode):
"""Validate API key."""
api_key_valid = None
errors, description_placeholders = {}, {}
try:
owm_client = create_owm_client(api_key, mode)
owm_client = get_owm_client(api_key, mode)
api_key_valid = await owm_client.validate_key()
except RequestError as error:
errors["base"] = "cannot_connect"
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/components/openweathermap/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
OWM_MODE_AIRPOLLUTION,
OWM_MODE_FREE_FORECAST,
OWM_MODE_V30,
OWM_MODE_V40,
)
from .coordinator import OWMUpdateCoordinator

Expand Down Expand Up @@ -106,7 +107,7 @@ def __init__(
)
self.mode = mode

if mode == OWM_MODE_V30:
if mode in (OWM_MODE_V30, OWM_MODE_V40):
self._attr_supported_features = (
WeatherEntityFeature.FORECAST_DAILY
| WeatherEntityFeature.FORECAST_HOURLY
Expand All @@ -117,7 +118,7 @@ def __init__(
async def async_get_minute_forecast(self) -> dict[str, list[dict]] | dict:
"""Return Minute forecast."""

if self.mode == OWM_MODE_V30:
if self.mode in (OWM_MODE_V30, OWM_MODE_V40):
return self.coordinator.data[ATTR_API_MINUTE_FORECAST]
raise ServiceValidationError(
translation_domain=DOMAIN,
Expand Down
4 changes: 2 additions & 2 deletions tests/components/openweathermap/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ def owm_client_mock() -> Generator[AsyncMock]:
client.validate_key.return_value = True
with (
patch(
"homeassistant.components.openweathermap.create_owm_client",
"homeassistant.components.openweathermap.get_owm_client",
return_value=client,
),
patch(
"homeassistant.components.openweathermap.utils.create_owm_client",
"homeassistant.components.openweathermap.utils.get_owm_client",
return_value=client,
),
):
Expand Down
Loading
Loading