Skip to content

Commit

Permalink
Fix forecast condition sensors
Browse files Browse the repository at this point in the history
  • Loading branch information
Limych committed May 17, 2024
1 parent eca4435 commit 80c623b
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 56 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ for today and 2 days forward.
# Example configuration.yaml entry
gismeteo:
sweet_home:
sensors:
sensors: {}

dacha:
name: Our Country House
Expand Down
3 changes: 2 additions & 1 deletion config/configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ logger:
# debugpy:

gismeteo:
sweet_home: {}
sweet_home:
sensors: {}

dacha:
name: Our Country House
Expand Down
38 changes: 17 additions & 21 deletions custom_components/gismeteo/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,11 @@
ATTR_SUNSET,
CONDITION_FOG_CLASSES,
ENDPOINT_URL,
FORECAST_MODE_DAILY,
FORECAST_MODE_HOURLY,
PARSED_UPDATE_INTERVAL,
PARSER_URL_FORMAT,
PARSER_USER_AGENT,
PRECIPITATION_AMOUNT,
ForecastMode,
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -174,13 +173,13 @@ def current_data(self) -> dict[str, Any]:
"""Return current weather data."""
return self._current

def forecast_data(self, pos: int, mode: str = FORECAST_MODE_HOURLY):
def forecast_data(self, pos: int, mode: str = ForecastMode.HOURLY):
"""Return forecast data."""
forecast = []
now = dt_util.now()
for data in (
self._forecast_hourly
if mode == FORECAST_MODE_HOURLY
if mode == ForecastMode.HOURLY
else self._forecast_daily
):
fc_time = data.get(ATTR_FORECAST_TIME)
Expand Down Expand Up @@ -310,15 +309,15 @@ def _get(var: dict, ind: str, func: Callable | None = None) -> Any:
return None
return res

def condition(self, src=None, mode: str = FORECAST_MODE_HOURLY) -> str | None:
def condition(self, src=None, mode: str = ForecastMode.HOURLY) -> str | None:
"""Return the condition summary."""
src = src or self._current

cld = src.get(ATTR_FORECAST_CLOUD_COVERAGE)
if cld is None:
return None
if cld == 0:
if mode == FORECAST_MODE_DAILY or (
if mode == ForecastMode.DAILY or (
src.get(ATTR_SUNRISE)
< src.get(ATTR_FORECAST_TIME, dt_util.now())
< src.get(ATTR_SUNSET)
Expand Down Expand Up @@ -418,7 +417,7 @@ def wind_bearing_label(self, src=None) -> str | None:
7: "w",
8: "nw",
}[bearing]
except KeyError:
except KeyError: # pragma: no cover
_LOGGER.error('Unknown wind bearing value "%s"', bearing)
return None

Expand All @@ -443,7 +442,7 @@ def precipitation_type(self, src=None) -> str | None:
2: "snow",
3: "snow-rain",
}[pt]
except KeyError:
except KeyError: # pragma: no cover
_LOGGER.error('Unknown precipitation type value "%s"', pt)
return None

Expand All @@ -463,7 +462,7 @@ def precipitation_intensity(self, src=None) -> str | None:
2: "normal",
3: "heavy",
}[pt]
except KeyError:
except KeyError: # pragma: no cover
_LOGGER.error('Unknown precipitation type value "%s"', pt)
return None

Expand Down Expand Up @@ -509,27 +508,27 @@ def geomagnetic_field(self, src=None) -> int | None:

def pollen_birch(self, src=None) -> int | None:
"""Return birch pollen value."""
src = src or self.forecast_data(0, FORECAST_MODE_DAILY)
src = src or self.forecast_data(0, ForecastMode.DAILY)
return src.get(ATTR_FORECAST_POLLEN_BIRCH)

def pollen_grass(self, src=None) -> int | None:
"""Return grass pollen value."""
src = src or self.forecast_data(0, FORECAST_MODE_DAILY)
src = src or self.forecast_data(0, ForecastMode.DAILY)
return src.get(ATTR_FORECAST_POLLEN_GRASS)

def pollen_ragweed(self, src=None) -> int | None:
"""Return grass pollen value."""
src = src or self.forecast_data(0, FORECAST_MODE_DAILY)
src = src or self.forecast_data(0, ForecastMode.DAILY)
return src.get(ATTR_FORECAST_POLLEN_RAGWEED)

def uv_index(self, src=None) -> float | None:
"""Return UV index."""
src = src or self.forecast_data(0, FORECAST_MODE_DAILY)
src = src or self.forecast_data(0, ForecastMode.DAILY)
return src.get(ATTR_FORECAST_UV_INDEX)

def road_condition(self, src=None) -> str | None:
"""Return road condition."""
src = src or self.forecast_data(0, FORECAST_MODE_DAILY)
src = src or self.forecast_data(0, ForecastMode.DAILY)
rc = src.get(ATTR_FORECAST_ROAD_CONDITION)
if not rc:
return None
Expand All @@ -540,17 +539,17 @@ def road_condition(self, src=None) -> str | None:
}
try:
return rcs[rc]
except KeyError:
except KeyError: # pragma: no cover
_LOGGER.error('Unknown road condition value "%s"', rc)
return None

def forecast(self, mode: str = FORECAST_MODE_HOURLY) -> list[GismeteoForecast]:
def forecast(self, mode: str = ForecastMode.HOURLY) -> list[GismeteoForecast]:
"""Return the forecast array."""
now = dt_util.now()
forecast = []
for i in (
self._forecast_hourly
if mode == FORECAST_MODE_HOURLY
if mode == ForecastMode.HOURLY
else self._forecast_daily
):
fc_time = i.get(ATTR_FORECAST_TIME)
Expand Down Expand Up @@ -582,10 +581,7 @@ def forecast(self, mode: str = FORECAST_MODE_HOURLY) -> list[GismeteoForecast]:
if v is not None
}

if (
mode == FORECAST_MODE_DAILY
and i.get(ATTR_FORECAST_TEMP_LOW) is not None
):
if mode == ForecastMode.DAILY and i.get(ATTR_FORECAST_TEMP_LOW) is not None:
data[ATTR_FORECAST_NATIVE_TEMP_LOW] = i.get(ATTR_FORECAST_TEMP_LOW)

if fc_time < now:
Expand Down
14 changes: 10 additions & 4 deletions custom_components/gismeteo/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"""

from datetime import timedelta
from enum import StrEnum
from typing import Final

from homeassistant.components.sensor import SensorDeviceClass, SensorEntityDescription
Expand Down Expand Up @@ -35,7 +36,7 @@
# Base component constants
NAME: Final = "Gismeteo"
DOMAIN: Final = "gismeteo"
VERSION: Final = "3.0.0-beta2"
VERSION: Final = "3.0.0-beta3"
ATTRIBUTION: Final = "Data provided by Gismeteo"
ISSUE_URL: Final = "https://github.com/Limych/ha-gismeteo/issues"
#
Expand All @@ -62,9 +63,6 @@
CONF_YAML: Final = "_yaml"
CONF_PLATFORM_FORMAT: Final = "_platform_{}"

FORECAST_MODE_HOURLY: Final = "hourly"
FORECAST_MODE_DAILY: Final = "daily"

# Defaults
DEFAULT_NAME: Final = "Gismeteo"

Expand Down Expand Up @@ -133,6 +131,14 @@

DEVICE_CLASS_TPL: Final = DOMAIN + "__{}"


class ForecastMode(StrEnum):
"""Forecast modes."""

HOURLY = "hourly"
DAILY = "daily"


SENSOR_DESCRIPTIONS: Final = (
SensorEntityDescription(
key=ATTR_FORECAST_CONDITION,
Expand Down
2 changes: 1 addition & 1 deletion custom_components/gismeteo/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
"requirements": [
"beautifulsoup4~=4.12"
],
"version": "3.0.0-beta2"
"version": "3.0.0-beta3"
}
19 changes: 13 additions & 6 deletions custom_components/gismeteo/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
COORDINATOR,
DOMAIN,
DOMAIN_YAML,
FORECAST_MODE_DAILY,
FORECAST_SENSOR_DESCRIPTIONS,
SENSOR_DESCRIPTIONS,
ForecastMode,
)
from .entity import GismeteoEntity

Expand Down Expand Up @@ -192,11 +192,18 @@ def native_value(self) -> StateType | date | datetime | Decimal:
"""Return the value reported by the sensor."""
try:

return getattr(self._gismeteo, self.entity_description.key)(
self._gismeteo.forecast_data(self._day, FORECAST_MODE_DAILY)
if self._day is not None
else None
)
if self._day is None:
res = getattr(self._gismeteo, self.entity_description.key)()
else:
forecast = self._gismeteo.forecast_data(self._day, ForecastMode.DAILY)
if self.entity_description.key == ATTR_FORECAST_CONDITION:
res = getattr(self._gismeteo, self.entity_description.key)(
forecast, ForecastMode.DAILY
)
else:
res = getattr(self._gismeteo, self.entity_description.key)(forecast)

return res

except KeyError: # pragma: no cover
_LOGGER.warning(
Expand Down
13 changes: 3 additions & 10 deletions custom_components/gismeteo/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,7 @@
from homeassistant.core import HomeAssistant, callback

from . import GismeteoDataUpdateCoordinator, _convert_yaml_config, deslugify
from .const import (
ATTRIBUTION,
COORDINATOR,
DOMAIN,
DOMAIN_YAML,
FORECAST_MODE_DAILY,
FORECAST_MODE_HOURLY,
)
from .const import ATTRIBUTION, COORDINATOR, DOMAIN, DOMAIN_YAML, ForecastMode
from .entity import GismeteoEntity

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -145,9 +138,9 @@ def uv_index(self) -> float | None:
@callback
def _async_forecast_daily(self) -> list[Forecast] | None:
"""Return the daily forecast in native units."""
return self._gismeteo.forecast(FORECAST_MODE_DAILY)
return self._gismeteo.forecast(ForecastMode.DAILY)

@callback
def _async_forecast_hourly(self) -> list[Forecast] | None:
"""Return the hourly forecast in native units."""
return self._gismeteo.forecast(FORECAST_MODE_HOURLY)
return self._gismeteo.forecast(ForecastMode.HOURLY)
20 changes: 8 additions & 12 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
ATTR_FORECAST_PRECIPITATION_TYPE,
ATTR_SUNRISE,
CONDITION_FOG_CLASSES,
FORECAST_MODE_DAILY,
ForecastMode,
)
from homeassistant.components.weather import (
ATTR_CONDITION_CLEAR_NIGHT,
Expand Down Expand Up @@ -494,7 +494,7 @@ async def test_condition():
assert gismeteo.condition() == ATTR_CONDITION_SNOWY
assert gismeteo.condition(gismeteo.current_data) == ATTR_CONDITION_SNOWY

gismeteo_d = await init_gismeteo(FORECAST_MODE_DAILY)
gismeteo_d = await init_gismeteo(ForecastMode.DAILY)
data = gismeteo.current_data

data[ATTR_FORECAST_CLOUD_COVERAGE] = None
Expand Down Expand Up @@ -775,7 +775,7 @@ async def test_pollen_birch():

for day, exp in enumerate([2, 2, 2, 1, 1, 3, 2]):
assert (
gismeteo_d.pollen_birch(gismeteo_d.forecast_data(day, FORECAST_MODE_DAILY))
gismeteo_d.pollen_birch(gismeteo_d.forecast_data(day, ForecastMode.DAILY))
== exp
)

Expand All @@ -788,7 +788,7 @@ async def test_pollen_grass():

for day, exp in enumerate([None, None, None, None, None, None, None]):
assert (
gismeteo_d.pollen_grass(gismeteo_d.forecast_data(day, FORECAST_MODE_DAILY))
gismeteo_d.pollen_grass(gismeteo_d.forecast_data(day, ForecastMode.DAILY))
== exp
)

Expand All @@ -801,9 +801,7 @@ async def test_pollen_ragweed():

for day, exp in enumerate([None, None, None, None, None, None, None]):
assert (
gismeteo_d.pollen_ragweed(
gismeteo_d.forecast_data(day, FORECAST_MODE_DAILY)
)
gismeteo_d.pollen_ragweed(gismeteo_d.forecast_data(day, ForecastMode.DAILY))
== exp
)

Expand All @@ -816,7 +814,7 @@ async def test_uv_index():

for day, exp in enumerate([2, 4, 3, 5, 7, 1, 7]):
assert (
gismeteo_d.uv_index(gismeteo_d.forecast_data(day, FORECAST_MODE_DAILY))
gismeteo_d.uv_index(gismeteo_d.forecast_data(day, ForecastMode.DAILY))
== exp
)

Expand All @@ -829,9 +827,7 @@ async def test_road_condition():

for day, exp in enumerate(["dry", "dry", "dry", "dry", None, None, None]):
assert (
gismeteo_d.road_condition(
gismeteo_d.forecast_data(day, FORECAST_MODE_DAILY)
)
gismeteo_d.road_condition(gismeteo_d.forecast_data(day, ForecastMode.DAILY))
== exp
)

Expand All @@ -845,7 +841,7 @@ async def test_road_condition():
# ):
# gismeteo_d = await init_gismeteo()
#
# assert gismeteo_d.forecast(FORECAST_MODE_DAILY) == [
# assert gismeteo_d.forecast(ForecastMode.DAILY) == [
# {
# "datetime": datetime(2021, 2, 26, tzinfo=TZ180),
# "condition": "rainy",
Expand Down

0 comments on commit 80c623b

Please sign in to comment.