Environment Canada: Add a detailed forecast action (#138806)
* Add forecast service. * Add detailed Environment Canada forecast data. * Add icon and translations. * Fix missing commas * Add const. * Add test.pull/138235/head
parent
0a0a96fb3b
commit
406f894dc1
|
@ -5,3 +5,4 @@ ATTR_STATION = "station"
|
||||||
CONF_STATION = "station"
|
CONF_STATION = "station"
|
||||||
CONF_TITLE = "title"
|
CONF_TITLE = "title"
|
||||||
DOMAIN = "environment_canada"
|
DOMAIN = "environment_canada"
|
||||||
|
SERVICE_ENVIRONMENT_CANADA_FORECASTS = "get_forecasts"
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
"services": {
|
"services": {
|
||||||
"set_radar_type": {
|
"set_radar_type": {
|
||||||
"service": "mdi:radar"
|
"service": "mdi:radar"
|
||||||
|
},
|
||||||
|
"get_forecasts": {
|
||||||
|
"service": "mdi:weather-cloudy-clock"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
get_forecasts:
|
||||||
|
target:
|
||||||
|
entity:
|
||||||
|
integration: environment_canada
|
||||||
|
domain: weather
|
||||||
|
|
||||||
set_radar_type:
|
set_radar_type:
|
||||||
target:
|
target:
|
||||||
entity:
|
entity:
|
||||||
|
|
|
@ -113,6 +113,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
|
"get_forecasts": {
|
||||||
|
"name": "Get forecasts",
|
||||||
|
"description": "Retrieves the forecast from selected weather services."
|
||||||
|
},
|
||||||
"set_radar_type": {
|
"set_radar_type": {
|
||||||
"name": "Set radar type",
|
"name": "Set radar type",
|
||||||
"description": "Sets the type of radar image to retrieve.",
|
"description": "Sets the type of radar image to retrieve.",
|
||||||
|
|
|
@ -35,11 +35,16 @@ from homeassistant.const import (
|
||||||
UnitOfSpeed,
|
UnitOfSpeed,
|
||||||
UnitOfTemperature,
|
UnitOfTemperature,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import (
|
||||||
from homeassistant.helpers import entity_registry as er
|
HomeAssistant,
|
||||||
|
ServiceResponse,
|
||||||
|
SupportsResponse,
|
||||||
|
callback,
|
||||||
|
)
|
||||||
|
from homeassistant.helpers import entity_platform, entity_registry as er
|
||||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN, SERVICE_ENVIRONMENT_CANADA_FORECASTS
|
||||||
from .coordinator import ECConfigEntry, ECDataUpdateCoordinator
|
from .coordinator import ECConfigEntry, ECDataUpdateCoordinator
|
||||||
|
|
||||||
# Icon codes from http://dd.weatheroffice.ec.gc.ca/citypage_weather/
|
# Icon codes from http://dd.weatheroffice.ec.gc.ca/citypage_weather/
|
||||||
|
@ -78,6 +83,14 @@ async def async_setup_entry(
|
||||||
|
|
||||||
async_add_entities([ECWeatherEntity(config_entry.runtime_data.weather_coordinator)])
|
async_add_entities([ECWeatherEntity(config_entry.runtime_data.weather_coordinator)])
|
||||||
|
|
||||||
|
platform = entity_platform.async_get_current_platform()
|
||||||
|
platform.async_register_entity_service(
|
||||||
|
SERVICE_ENVIRONMENT_CANADA_FORECASTS,
|
||||||
|
None,
|
||||||
|
"_async_environment_canada_forecasts",
|
||||||
|
supports_response=SupportsResponse.ONLY,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _calculate_unique_id(config_entry_unique_id: str | None, hourly: bool) -> str:
|
def _calculate_unique_id(config_entry_unique_id: str | None, hourly: bool) -> str:
|
||||||
"""Calculate unique ID."""
|
"""Calculate unique ID."""
|
||||||
|
@ -185,6 +198,23 @@ class ECWeatherEntity(
|
||||||
"""Return the hourly forecast in native units."""
|
"""Return the hourly forecast in native units."""
|
||||||
return get_forecast(self.ec_data, True)
|
return get_forecast(self.ec_data, True)
|
||||||
|
|
||||||
|
def _async_environment_canada_forecasts(self) -> ServiceResponse:
|
||||||
|
"""Return the native Environment Canada forecast."""
|
||||||
|
daily = []
|
||||||
|
for f in self.ec_data.daily_forecasts:
|
||||||
|
day = f.copy()
|
||||||
|
day["timestamp"] = day["timestamp"].isoformat()
|
||||||
|
daily.append(day)
|
||||||
|
|
||||||
|
hourly = []
|
||||||
|
for f in self.ec_data.hourly_forecasts:
|
||||||
|
hour = f.copy()
|
||||||
|
hour["timestamp"] = hour["period"].isoformat()
|
||||||
|
del hour["period"]
|
||||||
|
hourly.append(hour)
|
||||||
|
|
||||||
|
return {"daily_forecast": daily, "hourly_forecast": hourly}
|
||||||
|
|
||||||
|
|
||||||
def get_forecast(ec_data, hourly) -> list[Forecast] | None:
|
def get_forecast(ec_data, hourly) -> list[Forecast] | None:
|
||||||
"""Build the forecast array."""
|
"""Build the forecast array."""
|
||||||
|
|
|
@ -37,6 +37,7 @@ async def init_integration(hass: HomeAssistant, ec_data) -> MockConfigEntry:
|
||||||
weather_mock.conditions = ec_data["conditions"]
|
weather_mock.conditions = ec_data["conditions"]
|
||||||
weather_mock.alerts = ec_data["alerts"]
|
weather_mock.alerts = ec_data["alerts"]
|
||||||
weather_mock.daily_forecasts = ec_data["daily_forecasts"]
|
weather_mock.daily_forecasts = ec_data["daily_forecasts"]
|
||||||
|
weather_mock.hourly_forecasts = ec_data["hourly_forecasts"]
|
||||||
weather_mock.metadata = ec_data["metadata"]
|
weather_mock.metadata = ec_data["metadata"]
|
||||||
|
|
||||||
radar_mock = mock_ec()
|
radar_mock = mock_ec()
|
||||||
|
|
|
@ -19,6 +19,9 @@ def ec_data():
|
||||||
if t := weather.get("timestamp"):
|
if t := weather.get("timestamp"):
|
||||||
with contextlib.suppress(ValueError):
|
with contextlib.suppress(ValueError):
|
||||||
weather["timestamp"] = datetime.fromisoformat(t)
|
weather["timestamp"] = datetime.fromisoformat(t)
|
||||||
|
elif t := weather.get("period"):
|
||||||
|
with contextlib.suppress(ValueError):
|
||||||
|
weather["period"] = datetime.fromisoformat(t)
|
||||||
return weather
|
return weather
|
||||||
|
|
||||||
return json.loads(
|
return json.loads(
|
||||||
|
|
|
@ -238,6 +238,224 @@
|
||||||
"timestamp": "2022-10-09 15:00:00+00:00"
|
"timestamp": "2022-10-09 15:00:00+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"hourly_forecasts": [
|
||||||
|
{
|
||||||
|
"period": "2025-02-19T19:00:00+00:00",
|
||||||
|
"condition": "A mix of sun and cloud",
|
||||||
|
"temperature": -11,
|
||||||
|
"icon_code": "02",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-19T20:00:00+00:00",
|
||||||
|
"condition": "A mix of sun and cloud",
|
||||||
|
"temperature": -10,
|
||||||
|
"icon_code": "02",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-19T21:00:00+00:00",
|
||||||
|
"condition": "A mix of sun and cloud",
|
||||||
|
"temperature": -10,
|
||||||
|
"icon_code": "02",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-19T22:00:00+00:00",
|
||||||
|
"condition": "A mix of sun and cloud",
|
||||||
|
"temperature": -11,
|
||||||
|
"icon_code": "02",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-19T23:00:00+00:00",
|
||||||
|
"condition": "Mainly cloudy",
|
||||||
|
"temperature": -11,
|
||||||
|
"icon_code": "33",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T00:00:00+00:00",
|
||||||
|
"condition": "Cloudy",
|
||||||
|
"temperature": -12,
|
||||||
|
"icon_code": "10",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T01:00:00+00:00",
|
||||||
|
"condition": "Cloudy",
|
||||||
|
"temperature": -13,
|
||||||
|
"icon_code": "10",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T02:00:00+00:00",
|
||||||
|
"condition": "Cloudy",
|
||||||
|
"temperature": -13,
|
||||||
|
"icon_code": "10",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T03:00:00+00:00",
|
||||||
|
"condition": "Mainly cloudy",
|
||||||
|
"temperature": -14,
|
||||||
|
"icon_code": "33",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T04:00:00+00:00",
|
||||||
|
"condition": "Mainly cloudy",
|
||||||
|
"temperature": -14,
|
||||||
|
"icon_code": "33",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T05:00:00+00:00",
|
||||||
|
"condition": "Mainly cloudy",
|
||||||
|
"temperature": -15,
|
||||||
|
"icon_code": "33",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T06:00:00+00:00",
|
||||||
|
"condition": "Mainly cloudy",
|
||||||
|
"temperature": -15,
|
||||||
|
"icon_code": "33",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T07:00:00+00:00",
|
||||||
|
"condition": "Mainly cloudy",
|
||||||
|
"temperature": -15,
|
||||||
|
"icon_code": "33",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T08:00:00+00:00",
|
||||||
|
"condition": "Mainly cloudy",
|
||||||
|
"temperature": -16,
|
||||||
|
"icon_code": "33",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T09:00:00+00:00",
|
||||||
|
"condition": "Mainly cloudy",
|
||||||
|
"temperature": -16,
|
||||||
|
"icon_code": "33",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T10:00:00+00:00",
|
||||||
|
"condition": "Partly cloudy",
|
||||||
|
"temperature": -16,
|
||||||
|
"icon_code": "32",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T11:00:00+00:00",
|
||||||
|
"condition": "Partly cloudy",
|
||||||
|
"temperature": -16,
|
||||||
|
"icon_code": "32",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "W"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T12:00:00+00:00",
|
||||||
|
"condition": "A mix of sun and cloud",
|
||||||
|
"temperature": -16,
|
||||||
|
"icon_code": "02",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 5,
|
||||||
|
"wind_direction": "VR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T13:00:00+00:00",
|
||||||
|
"condition": "A mix of sun and cloud",
|
||||||
|
"temperature": -15,
|
||||||
|
"icon_code": "02",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 5,
|
||||||
|
"wind_direction": "VR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T14:00:00+00:00",
|
||||||
|
"condition": "A mix of sun and cloud",
|
||||||
|
"temperature": -14,
|
||||||
|
"icon_code": "02",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 5,
|
||||||
|
"wind_direction": "VR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T15:00:00+00:00",
|
||||||
|
"condition": "A mix of sun and cloud",
|
||||||
|
"temperature": -13,
|
||||||
|
"icon_code": "02",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "NW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T16:00:00+00:00",
|
||||||
|
"condition": "Mainly cloudy",
|
||||||
|
"temperature": -11,
|
||||||
|
"icon_code": "03",
|
||||||
|
"precip_probability": 20,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "NW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T17:00:00+00:00",
|
||||||
|
"condition": "Periods of light snow",
|
||||||
|
"temperature": -10,
|
||||||
|
"icon_code": "16",
|
||||||
|
"precip_probability": 70,
|
||||||
|
"wind_speed": 10,
|
||||||
|
"wind_direction": "NW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"period": "2025-02-20T18:00:00+00:00",
|
||||||
|
"condition": "Periods of light snow",
|
||||||
|
"temperature": -8,
|
||||||
|
"icon_code": "16",
|
||||||
|
"precip_probability": 70,
|
||||||
|
"wind_speed": 20,
|
||||||
|
"wind_direction": "NW"
|
||||||
|
}
|
||||||
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"attribution": "Data provided by Environment Canada",
|
"attribution": "Data provided by Environment Canada",
|
||||||
"timestamp": "2022/10/3",
|
"timestamp": "2022/10/3",
|
||||||
|
|
|
@ -92,3 +92,337 @@
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_get_environment_canada_raw_forecast_data
|
||||||
|
dict({
|
||||||
|
'weather.home_forecast': dict({
|
||||||
|
'daily_forecast': list([
|
||||||
|
dict({
|
||||||
|
'icon_code': '30',
|
||||||
|
'period': 'Monday night',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': -1,
|
||||||
|
'temperature_class': 'low',
|
||||||
|
'text_summary': 'Clear. Fog patches developing after midnight. Low minus 1 with frost.',
|
||||||
|
'timestamp': '2022-10-03T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '00',
|
||||||
|
'period': 'Tuesday',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 18,
|
||||||
|
'temperature_class': 'high',
|
||||||
|
'text_summary': 'Sunny. Fog patches dissipating in the morning. High 18. UV index 5 or moderate.',
|
||||||
|
'timestamp': '2022-10-04T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '30',
|
||||||
|
'period': 'Tuesday night',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 3,
|
||||||
|
'temperature_class': 'low',
|
||||||
|
'text_summary': 'Clear. Fog patches developing overnight. Low plus 3.',
|
||||||
|
'timestamp': '2022-10-04T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '00',
|
||||||
|
'period': 'Wednesday',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 20,
|
||||||
|
'temperature_class': 'high',
|
||||||
|
'text_summary': 'Sunny. High 20.',
|
||||||
|
'timestamp': '2022-10-05T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '30',
|
||||||
|
'period': 'Wednesday night',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 9,
|
||||||
|
'temperature_class': 'low',
|
||||||
|
'text_summary': 'Clear. Low 9.',
|
||||||
|
'timestamp': '2022-10-05T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '02',
|
||||||
|
'period': 'Thursday',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 20,
|
||||||
|
'temperature_class': 'high',
|
||||||
|
'text_summary': 'A mix of sun and cloud. High 20.',
|
||||||
|
'timestamp': '2022-10-06T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '12',
|
||||||
|
'period': 'Thursday night',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 7,
|
||||||
|
'temperature_class': 'low',
|
||||||
|
'text_summary': 'Showers. Low 7.',
|
||||||
|
'timestamp': '2022-10-06T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '12',
|
||||||
|
'period': 'Friday',
|
||||||
|
'precip_probability': 40,
|
||||||
|
'temperature': 13,
|
||||||
|
'temperature_class': 'high',
|
||||||
|
'text_summary': 'Cloudy with 40 percent chance of showers. High 13.',
|
||||||
|
'timestamp': '2022-10-07T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '32',
|
||||||
|
'period': 'Friday night',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 1,
|
||||||
|
'temperature_class': 'low',
|
||||||
|
'text_summary': 'Cloudy periods. Low plus 1.',
|
||||||
|
'timestamp': '2022-10-07T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '02',
|
||||||
|
'period': 'Saturday',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 10,
|
||||||
|
'temperature_class': 'high',
|
||||||
|
'text_summary': 'A mix of sun and cloud. High 10.',
|
||||||
|
'timestamp': '2022-10-08T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '32',
|
||||||
|
'period': 'Saturday night',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 3,
|
||||||
|
'temperature_class': 'low',
|
||||||
|
'text_summary': 'Cloudy periods. Low plus 3.',
|
||||||
|
'timestamp': '2022-10-08T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'icon_code': '02',
|
||||||
|
'period': 'Sunday',
|
||||||
|
'precip_probability': 0,
|
||||||
|
'temperature': 12,
|
||||||
|
'temperature_class': 'high',
|
||||||
|
'text_summary': 'A mix of sun and cloud. High 12.',
|
||||||
|
'timestamp': '2022-10-09T15:00:00+00:00',
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
'hourly_forecast': list([
|
||||||
|
dict({
|
||||||
|
'condition': 'A mix of sun and cloud',
|
||||||
|
'icon_code': '02',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -11,
|
||||||
|
'timestamp': '2025-02-19T19:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'A mix of sun and cloud',
|
||||||
|
'icon_code': '02',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -10,
|
||||||
|
'timestamp': '2025-02-19T20:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'A mix of sun and cloud',
|
||||||
|
'icon_code': '02',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -10,
|
||||||
|
'timestamp': '2025-02-19T21:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'A mix of sun and cloud',
|
||||||
|
'icon_code': '02',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -11,
|
||||||
|
'timestamp': '2025-02-19T22:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Mainly cloudy',
|
||||||
|
'icon_code': '33',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -11,
|
||||||
|
'timestamp': '2025-02-19T23:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Cloudy',
|
||||||
|
'icon_code': '10',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -12,
|
||||||
|
'timestamp': '2025-02-20T00:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Cloudy',
|
||||||
|
'icon_code': '10',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -13,
|
||||||
|
'timestamp': '2025-02-20T01:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Cloudy',
|
||||||
|
'icon_code': '10',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -13,
|
||||||
|
'timestamp': '2025-02-20T02:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Mainly cloudy',
|
||||||
|
'icon_code': '33',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -14,
|
||||||
|
'timestamp': '2025-02-20T03:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Mainly cloudy',
|
||||||
|
'icon_code': '33',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -14,
|
||||||
|
'timestamp': '2025-02-20T04:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Mainly cloudy',
|
||||||
|
'icon_code': '33',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -15,
|
||||||
|
'timestamp': '2025-02-20T05:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Mainly cloudy',
|
||||||
|
'icon_code': '33',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -15,
|
||||||
|
'timestamp': '2025-02-20T06:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Mainly cloudy',
|
||||||
|
'icon_code': '33',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -15,
|
||||||
|
'timestamp': '2025-02-20T07:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Mainly cloudy',
|
||||||
|
'icon_code': '33',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -16,
|
||||||
|
'timestamp': '2025-02-20T08:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Mainly cloudy',
|
||||||
|
'icon_code': '33',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -16,
|
||||||
|
'timestamp': '2025-02-20T09:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Partly cloudy',
|
||||||
|
'icon_code': '32',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -16,
|
||||||
|
'timestamp': '2025-02-20T10:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Partly cloudy',
|
||||||
|
'icon_code': '32',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -16,
|
||||||
|
'timestamp': '2025-02-20T11:00:00+00:00',
|
||||||
|
'wind_direction': 'W',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'A mix of sun and cloud',
|
||||||
|
'icon_code': '02',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -16,
|
||||||
|
'timestamp': '2025-02-20T12:00:00+00:00',
|
||||||
|
'wind_direction': 'VR',
|
||||||
|
'wind_speed': 5,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'A mix of sun and cloud',
|
||||||
|
'icon_code': '02',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -15,
|
||||||
|
'timestamp': '2025-02-20T13:00:00+00:00',
|
||||||
|
'wind_direction': 'VR',
|
||||||
|
'wind_speed': 5,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'A mix of sun and cloud',
|
||||||
|
'icon_code': '02',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -14,
|
||||||
|
'timestamp': '2025-02-20T14:00:00+00:00',
|
||||||
|
'wind_direction': 'VR',
|
||||||
|
'wind_speed': 5,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'A mix of sun and cloud',
|
||||||
|
'icon_code': '02',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -13,
|
||||||
|
'timestamp': '2025-02-20T15:00:00+00:00',
|
||||||
|
'wind_direction': 'NW',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Mainly cloudy',
|
||||||
|
'icon_code': '03',
|
||||||
|
'precip_probability': 20,
|
||||||
|
'temperature': -11,
|
||||||
|
'timestamp': '2025-02-20T16:00:00+00:00',
|
||||||
|
'wind_direction': 'NW',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Periods of light snow',
|
||||||
|
'icon_code': '16',
|
||||||
|
'precip_probability': 70,
|
||||||
|
'temperature': -10,
|
||||||
|
'timestamp': '2025-02-20T17:00:00+00:00',
|
||||||
|
'wind_direction': 'NW',
|
||||||
|
'wind_speed': 10,
|
||||||
|
}),
|
||||||
|
dict({
|
||||||
|
'condition': 'Periods of light snow',
|
||||||
|
'icon_code': '16',
|
||||||
|
'precip_probability': 70,
|
||||||
|
'temperature': -8,
|
||||||
|
'timestamp': '2025-02-20T18:00:00+00:00',
|
||||||
|
'wind_direction': 'NW',
|
||||||
|
'wind_speed': 20,
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
|
|
@ -5,6 +5,10 @@ from typing import Any
|
||||||
|
|
||||||
from syrupy.assertion import SnapshotAssertion
|
from syrupy.assertion import SnapshotAssertion
|
||||||
|
|
||||||
|
from homeassistant.components.environment_canada.const import (
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_ENVIRONMENT_CANADA_FORECASTS,
|
||||||
|
)
|
||||||
from homeassistant.components.weather import (
|
from homeassistant.components.weather import (
|
||||||
DOMAIN as WEATHER_DOMAIN,
|
DOMAIN as WEATHER_DOMAIN,
|
||||||
SERVICE_GET_FORECASTS,
|
SERVICE_GET_FORECASTS,
|
||||||
|
@ -56,3 +60,22 @@ async def test_forecast_daily_with_some_previous_days_data(
|
||||||
return_response=True,
|
return_response=True,
|
||||||
)
|
)
|
||||||
assert response == snapshot
|
assert response == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get_environment_canada_raw_forecast_data(
|
||||||
|
hass: HomeAssistant, snapshot: SnapshotAssertion, ec_data: dict[str, Any]
|
||||||
|
) -> None:
|
||||||
|
"""Test forecast with half day at start."""
|
||||||
|
|
||||||
|
await init_integration(hass, ec_data)
|
||||||
|
|
||||||
|
response = await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_ENVIRONMENT_CANADA_FORECASTS,
|
||||||
|
{
|
||||||
|
"entity_id": "weather.home_forecast",
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
return_response=True,
|
||||||
|
)
|
||||||
|
assert response == snapshot
|
||||||
|
|
Loading…
Reference in New Issue