Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for Environment Canada date being wrong after midnight #121850

Merged
merged 11 commits into from
Jul 16, 2024
Merged
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
2 changes: 1 addition & 1 deletion homeassistant/components/environment_canada/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/environment_canada",
"iot_class": "cloud_polling",
"loggers": ["env_canada"],
"requirements": ["env-canada==0.7.1"]
"requirements": ["env-canada==0.7.2"]
}
68 changes: 18 additions & 50 deletions homeassistant/components/environment_canada/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

from __future__ import annotations

import datetime

from homeassistant.components.weather import (
ATTR_CONDITION_CLEAR_NIGHT,
ATTR_CONDITION_CLOUDY,
Expand Down Expand Up @@ -37,7 +35,6 @@
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import dt as dt_util

from . import device_info
from .const import DOMAIN
Expand Down Expand Up @@ -193,53 +190,24 @@ def get_forecast(ec_data, hourly) -> list[Forecast] | None:
if not (half_days := ec_data.daily_forecasts):
return None

today: Forecast = {
ATTR_FORECAST_TIME: dt_util.now().isoformat(),
ATTR_FORECAST_CONDITION: icon_code_to_condition(
int(half_days[0]["icon_code"])
),
ATTR_FORECAST_PRECIPITATION_PROBABILITY: int(
half_days[0]["precip_probability"]
),
}

if half_days[0]["temperature_class"] == "high":
today.update(
{
ATTR_FORECAST_NATIVE_TEMP: int(half_days[0]["temperature"]),
ATTR_FORECAST_NATIVE_TEMP_LOW: int(half_days[1]["temperature"]),
}
)
half_days = half_days[2:]
else:
today.update(
{
ATTR_FORECAST_NATIVE_TEMP: None,
ATTR_FORECAST_NATIVE_TEMP_LOW: int(half_days[0]["temperature"]),
}
)
half_days = half_days[1:]

forecast_array.append(today)

for day, high, low in zip(
range(1, 6), range(0, 9, 2), range(1, 10, 2), strict=False
):
forecast_array.append(
{
ATTR_FORECAST_TIME: (
dt_util.now() + datetime.timedelta(days=day)
).isoformat(),
ATTR_FORECAST_NATIVE_TEMP: int(half_days[high]["temperature"]),
ATTR_FORECAST_NATIVE_TEMP_LOW: int(half_days[low]["temperature"]),
ATTR_FORECAST_CONDITION: icon_code_to_condition(
int(half_days[high]["icon_code"])
),
ATTR_FORECAST_PRECIPITATION_PROBABILITY: int(
half_days[high]["precip_probability"]
),
}
)
def get_day_forecast(fcst: list[dict[str, str]]) -> Forecast:
high_temp = int(fcst[0]["temperature"]) if len(fcst) == 2 else None
return {
ATTR_FORECAST_TIME: fcst[0]["timestamp"],
ATTR_FORECAST_NATIVE_TEMP: high_temp,
ATTR_FORECAST_NATIVE_TEMP_LOW: int(fcst[-1]["temperature"]),
ATTR_FORECAST_PRECIPITATION_PROBABILITY: int(
fcst[0]["precip_probability"]
),
ATTR_FORECAST_CONDITION: icon_code_to_condition(
int(fcst[0]["icon_code"])
),
}

i = 2 if half_days[0]["temperature_class"] == "high" else 1
forecast_array.append(get_day_forecast(half_days[0:i]))
for i in range(i, len(half_days) - 1, 2):
forecast_array.append(get_day_forecast(half_days[i : i + 2])) # noqa: PERF401

else:
forecast_array.extend(
Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ enocean==0.50
enturclient==0.2.4

# homeassistant.components.environment_canada
env-canada==0.7.1
env-canada==0.7.2

# homeassistant.components.season
ephem==4.1.5
Expand Down
2 changes: 1 addition & 1 deletion requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ energyzero==2.1.1
enocean==0.50

# homeassistant.components.environment_canada
env-canada==0.7.1
env-canada==0.7.2

# homeassistant.components.season
ephem==4.1.5
Expand Down
66 changes: 66 additions & 0 deletions tests/components/environment_canada/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,67 @@
"""Tests for the Environment Canada integration."""

from datetime import UTC, datetime
from unittest.mock import AsyncMock, MagicMock, patch

from homeassistant.components.environment_canada.const import CONF_STATION, DOMAIN
from homeassistant.const import CONF_LANGUAGE, CONF_LATITUDE, CONF_LONGITUDE
from homeassistant.core import HomeAssistant

from tests.common import MockConfigEntry

FIXTURE_USER_INPUT = {
CONF_LATITUDE: 55.55,
CONF_LONGITUDE: 42.42,
CONF_STATION: "XX/1234567",
CONF_LANGUAGE: "Gibberish",
}


async def init_integration(hass: HomeAssistant, ec_data) -> MockConfigEntry:
"""Set up the Environment Canada integration in Home Assistant."""

def mock_ec():
ec_mock = MagicMock()
ec_mock.station_id = FIXTURE_USER_INPUT[CONF_STATION]
ec_mock.lat = FIXTURE_USER_INPUT[CONF_LATITUDE]
ec_mock.lon = FIXTURE_USER_INPUT[CONF_LONGITUDE]
ec_mock.language = FIXTURE_USER_INPUT[CONF_LANGUAGE]
ec_mock.update = AsyncMock()
return ec_mock

config_entry = MockConfigEntry(domain=DOMAIN, data=FIXTURE_USER_INPUT, title="Home")
config_entry.add_to_hass(hass)

weather_mock = mock_ec()
ec_data["metadata"]["timestamp"] = datetime(2022, 10, 4, tzinfo=UTC)
weather_mock.conditions = ec_data["conditions"]
weather_mock.alerts = ec_data["alerts"]
weather_mock.daily_forecasts = ec_data["daily_forecasts"]
weather_mock.metadata = ec_data["metadata"]

radar_mock = mock_ec()
radar_mock.image = b"GIF..."
radar_mock.timestamp = datetime(2022, 10, 4, tzinfo=UTC)

with (
patch(
"homeassistant.components.environment_canada.ECWeather",
return_value=weather_mock,
),
patch(
"homeassistant.components.environment_canada.ECAirQuality",
return_value=mock_ec(),
),
patch(
"homeassistant.components.environment_canada.ECRadar",
return_value=radar_mock,
),
patch(
"homeassistant.components.environment_canada.config_flow.ECWeather",
return_value=weather_mock,
),
):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()

return config_entry
Original file line number Diff line number Diff line change
Expand Up @@ -135,95 +135,107 @@
"icon_code": "30",
"temperature": -1,
"temperature_class": "low",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-03 15:00:00+00:00"
},
{
"period": "Tuesday",
"text_summary": "Sunny. Fog patches dissipating in the morning. High 18. UV index 5 or moderate.",
"icon_code": "00",
"temperature": 18,
"temperature_class": "high",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-04 15:00:00+00:00"
},
{
"period": "Tuesday night",
"text_summary": "Clear. Fog patches developing overnight. Low plus 3.",
"icon_code": "30",
"temperature": 3,
"temperature_class": "low",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-04 15:00:00+00:00"
},
{
"period": "Wednesday",
"text_summary": "Sunny. High 20.",
"icon_code": "00",
"temperature": 20,
"temperature_class": "high",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-05 15:00:00+00:00"
},
{
"period": "Wednesday night",
"text_summary": "Clear. Low 9.",
"icon_code": "30",
"temperature": 9,
"temperature_class": "low",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-05 15:00:00+00:00"
},
{
"period": "Thursday",
"text_summary": "A mix of sun and cloud. High 20.",
"icon_code": "02",
"temperature": 20,
"temperature_class": "high",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-06 15:00:00+00:00"
},
{
"period": "Thursday night",
"text_summary": "Showers. Low 7.",
"icon_code": "12",
"temperature": 7,
"temperature_class": "low",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-06 15:00:00+00:00"
},
{
"period": "Friday",
"text_summary": "Cloudy with 40 percent chance of showers. High 13.",
"icon_code": "12",
"temperature": 13,
"temperature_class": "high",
"precip_probability": 40
"precip_probability": 40,
"timestamp": "2022-10-07 15:00:00+00:00"
},
{
"period": "Friday night",
"text_summary": "Cloudy periods. Low plus 1.",
"icon_code": "32",
"temperature": 1,
"temperature_class": "low",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-07 15:00:00+00:00"
},
{
"period": "Saturday",
"text_summary": "A mix of sun and cloud. High 10.",
"icon_code": "02",
"temperature": 10,
"temperature_class": "high",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-08 15:00:00+00:00"
},
{
"period": "Saturday night",
"text_summary": "Cloudy periods. Low plus 3.",
"icon_code": "32",
"temperature": 3,
"temperature_class": "low",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-08 15:00:00+00:00"
},
{
"period": "Sunday",
"text_summary": "A mix of sun and cloud. High 12.",
"icon_code": "02",
"temperature": 12,
"temperature_class": "high",
"precip_probability": 0
"precip_probability": 0,
"timestamp": "2022-10-09 15:00:00+00:00"
}
],
"metadata": {
Expand Down
94 changes: 94 additions & 0 deletions tests/components/environment_canada/snapshots/test_weather.ambr
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# serializer version: 1
# name: test_forecast_daily
dict({
'weather.home_forecast': dict({
'forecast': list([
dict({
'condition': 'sunny',
'datetime': '2022-10-04 15:00:00+00:00',
'precipitation_probability': 0,
'temperature': 18.0,
'templow': 3.0,
}),
dict({
'condition': 'sunny',
'datetime': '2022-10-05 15:00:00+00:00',
'precipitation_probability': 0,
'temperature': 20.0,
'templow': 9.0,
}),
dict({
'condition': 'partlycloudy',
'datetime': '2022-10-06 15:00:00+00:00',
'precipitation_probability': 0,
'temperature': 20.0,
'templow': 7.0,
}),
dict({
'condition': 'rainy',
'datetime': '2022-10-07 15:00:00+00:00',
'precipitation_probability': 40,
'temperature': 13.0,
'templow': 1.0,
}),
dict({
'condition': 'partlycloudy',
'datetime': '2022-10-08 15:00:00+00:00',
'precipitation_probability': 0,
'temperature': 10.0,
'templow': 3.0,
}),
]),
}),
})
# ---
# name: test_forecast_daily_with_some_previous_days_data
dict({
'weather.home_forecast': dict({
'forecast': list([
dict({
'condition': 'clear-night',
'datetime': '2022-10-03 15:00:00+00:00',
'precipitation_probability': 0,
'temperature': None,
'templow': -1.0,
}),
dict({
'condition': 'sunny',
'datetime': '2022-10-04 15:00:00+00:00',
'precipitation_probability': 0,
'temperature': 18.0,
'templow': 3.0,
}),
dict({
'condition': 'sunny',
'datetime': '2022-10-05 15:00:00+00:00',
'precipitation_probability': 0,
'temperature': 20.0,
'templow': 9.0,
}),
dict({
'condition': 'partlycloudy',
'datetime': '2022-10-06 15:00:00+00:00',
'precipitation_probability': 0,
'temperature': 20.0,
'templow': 7.0,
}),
dict({
'condition': 'rainy',
'datetime': '2022-10-07 15:00:00+00:00',
'precipitation_probability': 40,
'temperature': 13.0,
'templow': 1.0,
}),
dict({
'condition': 'partlycloudy',
'datetime': '2022-10-08 15:00:00+00:00',
'precipitation_probability': 0,
'temperature': 10.0,
'templow': 3.0,
}),
]),
}),
})
# ---
Loading