Skip to content

Commit

Permalink
Include Reported condition (#30)
Browse files Browse the repository at this point in the history
* Added reported condition code

* Sorted CONDITION_MAP

* Added comments about conditions

* Moved ice pellets to ATTR_CONDITION_HAIL

* Moved sleet, freezing drizzle to SNOWY_RAINY, added 1219

* Updated readme
  • Loading branch information
iprak authored Apr 13, 2023
1 parent 91706ef commit 39796ac
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 49 deletions.
31 changes: 18 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,34 @@
The `WeatherAPI` integration displays weather forecast, air quality and ultra violet data from [WeatherAPI](https://www.weatherapi.com/).

You should see 3 entities generated for a location starting with the id:
* sensor.weatherapi_
* air_quality.weatherapi_
* weather.weatherapi_

- sensor.weatherapi\_
- air*quality.weatherapi*
- weather.weatherapi\_

# Installation

* First obtain a free API key by signing up with [WeatherAPI](https://www.weatherapi.com/). The free API key is limited to 3 day forecast and 1,000,000 calls per month. You can get 5 or more days of forecast with a [paid account](https://www.weatherapi.com/pricing.aspx).
* Download all the files from `custom_components/weatherapi/` into `<config directory>/custom_components/weatherapi/`.
* Restart HomeAssistant.
* `WeatherAPI` can now be added to your Home Assistant instance via the user interface, by using the `Add Integration` button in Integrations page on your Home Assistant instance.
* You should see one weather entity and some air quality/UV index entities. All entity ids will start as `weather/sensor.weatherapi_location`. Entity id can be adjusted from `Entities` page.
- First obtain a free API key by signing up with [WeatherAPI](https://www.weatherapi.com/). The free API key is limited to 3 day forecast and 1,000,000 calls per month. You can get 5 or more days of forecast with a [paid account](https://www.weatherapi.com/pricing.aspx).
- Download all the files from `custom_components/weatherapi/` into `<config directory>/custom_components/weatherapi/`.
- Restart HomeAssistant.
- `WeatherAPI` can now be added to your Home Assistant instance via the user interface, by using the `Add Integration` button in Integrations page on your Home Assistant instance.
- You should see one weather entity and some air quality/UV index entities. All entity ids will start as `weather/sensor.weatherapi_location`. Entity id can be adjusted from `Entities` page.

# Configuration

The integration can be configured using the `CONFIGURE` button on the Integrations page.

![image](https://user-images.githubusercontent.com/6459774/212574703-8942d9f5-bbfe-4870-a5d5-96d72fefdd7c.png)

* Configure generation of weather related sensors. If unchecked, the sensors would become disabled and would need to be manually deleted.
* Configure generation of forecast and hourly forecast.
* Configure hourly forecast to start at midnight or the current hour.
- Configure generation of weather related sensors. If unchecked, the sensors would become disabled and would need to be manually deleted.
- Configure generation of forecast and hourly forecast.
- Configure hourly forecast to start at midnight or the current hour.

# Additional Data

- The weather entity has the `reported_condition` which is the original reported condition ([condition codes](https://www.weatherapi.com/docs/weather_conditions.json)).

# Breaking Changes
* [v0.7](https://github.com/iprak/weatherapi/releases): If you had upgraded to v0.6 then the previous UV and air_quality entities will appear unavailable. Now individual entities for air quality parameters are created.
* [v0.6](https://github.com/iprak/weatherapi/releases): You might get duplicated/invalid entity after upgrading to v0.6. This can be fixed by deleting the inactive entity and adjusting the id of the active entity from `Configuration -> Devices & Services -> Entities`.

- [v0.7](https://github.com/iprak/weatherapi/releases): If you had upgraded to v0.6 then the previous UV and air_quality entities will appear unavailable. Now individual entities for air quality parameters are created.
- [v0.6](https://github.com/iprak/weatherapi/releases): You might get duplicated/invalid entity after upgrading to v0.6. This can be fixed by deleting the inactive entity and adjusting the id of the active entity from `Configuration -> Devices & Services -> Entities`.
87 changes: 56 additions & 31 deletions custom_components/weatherapi/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
ATTR_AIR_QUALITY_US_EPA_INDEX: Final = "us-epa-index"
ATTR_AIR_QUALITY_UK_DEFRA_INDEX: Final = "gb-defra-index"
ATTR_AIR_QUALITY_UK_DEFRA_INDEX_BAND: Final = "band"
ATTR_REPORTED_CONDITION: Final = "reported_condition"

DATA_FORECAST: Final = "forecast"

Expand All @@ -42,44 +43,68 @@
DEFAULT_HOURLY_FORECAST: Final = False
DEFAULT_IGNORE_PAST_HOUR: Final = True


# https://www.weatherapi.com/docs/weather_conditions.json
CONDITION_MAP: Final[dict[str, list[int]]] = {
ATTR_CONDITION_SUNNY: [1000],
# ATTR_CONDITION_CLEAR_NIGHT: [1000],
ATTR_CONDITION_PARTLYCLOUDY: [1003],
ATTR_CONDITION_CLOUDY: [1006, 1009],
ATTR_CONDITION_FOG: [1030, 1135, 1147],
ATTR_CONDITION_RAINY: [1063, 1150, 1153, 1168, 1180, 1183, 1186, 1189, 1240],
ATTR_CONDITION_CLOUDY: [1006, 1009], # Cloudy, Overcast
# ATTR_CONDITION_EXCEPTIONAL
ATTR_CONDITION_FOG: [1030, 1135, 1147], # Mist, Fog, Freezing fog
ATTR_CONDITION_HAIL: [
1237,
1237, # Ice pellets
1261, # Light showers of ice pellets
1264, # Moderate or heavy showers of ice pellets
],
ATTR_CONDITION_LIGHTNING: [1087], # Thundery outbreaks possible
ATTR_CONDITION_LIGHTNING_RAINY: [
1273, # Patchy light rain with thunder
1276, # Moderate or heavy rain with thunder
],
ATTR_CONDITION_PARTLYCLOUDY: [1003],
ATTR_CONDITION_POURING: [
1192, # Heavy rain at times
1195, # Heavy rain
1243, # Moderate or heavy rain shower
1246, # Torrential rain shower
],
ATTR_CONDITION_RAINY: [
1063, # Patchy rain possible
1150, # Patchy light drizzle
1153, # Light drizzle
1180, # Patchy light rain
1183, # Light rain
1186, # Moderate rain at times
1189, # Moderate rain
1240, # Light rain shower
],
ATTR_CONDITION_LIGHTNING: [1087],
ATTR_CONDITION_LIGHTNING_RAINY: [1273, 1276],
ATTR_CONDITION_POURING: [1171, 1192, 1195, 1243, 1246],
ATTR_CONDITION_SNOWY: [
1066,
1069,
1114,
1117,
1210,
1213,
1216,
1222,
1225,
1279,
1282,
1066, # Patchy snow possible
1114, # Blowing snow
1117, # Blizzard
1210, # Patchy light snow
1213, # Light snow
1216, # Patchy moderate snow
1219, # Moderate snow
1222, # Patchy heavy snow
1225, # Heavy snow
1279, # Patchy light snow with thunder
1282, # Moderate or heavy snow with thunder
],
ATTR_CONDITION_SNOWY_RAINY: [
1072,
1198,
1201,
1204,
1207,
1249,
1252,
1255,
1258,
1261,
1264,
1069, # Patchy sleet possible
1072, # Patchy freezing drizzle possible
1168, # Freezing drizzle
1171, # Heavy freezing drizzle
1198, # Light freezing rain
1201, # Moderate or heavy freezing rain
1204, # Light sleet
1207, # Moderate or heavy sleet
1249, # Light sleet showers
1252, # Moderate or heavy sleet showers
1255, # Light snow showers
1258, # Moderate or heavy snow showers
],
ATTR_CONDITION_SUNNY: [1000], # Sunny
# ATTR_CONDITION_WINDY
# ATTR_CONDITION_WINDY_VARIANT
}
17 changes: 13 additions & 4 deletions custom_components/weatherapi/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from custom_components.weatherapi.const import (
ATTR_AIR_QUALITY_UK_DEFRA_INDEX,
ATTR_AIR_QUALITY_US_EPA_INDEX,
ATTR_REPORTED_CONDITION,
ATTR_UV,
ATTR_WEATHER_CONDITION,
CONDITION_MAP,
Expand Down Expand Up @@ -329,6 +330,7 @@ def parse_forecast(self, json):
else:
condition = day.get("condition", {})
is_day = to_int(day.get("is_day", "1")) == 1
condition_code = condition.get("code")

day_entry = Forecast(
datetime=datetime_to_iso(forecastday.get("date")),
Expand All @@ -345,8 +347,9 @@ def parse_forecast(self, json):
wind_speed=to_float(
day.get("maxwind_kph" if is_metric else "maxwind_mph")
),
condition=parse_condition_code(condition.get("code"), is_day),
condition=parse_condition_code(condition_code, is_day),
)
day_entry[ATTR_REPORTED_CONDITION] = condition_code

entries.append(day_entry)

Expand Down Expand Up @@ -377,13 +380,17 @@ def parse_hour_forecast(self, data: any) -> Forecast:
).isoformat()

is_day = to_int(data.get("is_day", "1")) == 1
return Forecast(
condition_code = condition.get("code")

value = Forecast(
datetime=hour_forecast_time,
temperature=to_float(data.get("temp_c" if self.is_metric else "temp_f")),
precipitation_probability=data.get("chance_of_rain"),
wind_speed=to_float(data.get("wind_mph" if self.is_metric else "wind_kph")),
condition=parse_condition_code(condition.get("code"), is_day),
condition=parse_condition_code(condition_code, is_day),
)
value[ATTR_REPORTED_CONDITION] = condition_code
return value

def parse_current(self, json):
"""Parse the current weather JSON data."""
Expand All @@ -397,6 +404,7 @@ def parse_current(self, json):
condition = json.get("condition", {})
air_quality = json.get("air_quality", {})
is_day = to_int(json.get("is_day", "1")) == 1
condition_code = condition.get("code")

return {
ATTR_WEATHER_HUMIDITY: to_float(json.get("humidity")),
Expand All @@ -414,7 +422,8 @@ def parse_current(self, json):
json.get("vis_km" if is_metric else "vis_miles")
),
ATTR_UV: to_float(json.get("uv")),
ATTR_WEATHER_CONDITION: parse_condition_code(condition.get("code"), is_day),
ATTR_REPORTED_CONDITION: condition_code,
ATTR_WEATHER_CONDITION: parse_condition_code(condition_code, is_day),
ATTR_WEATHER_OZONE: to_float(air_quality.get("o3")),
# Air quality data pieces
ATTR_CO: to_float(air_quality.get("co")),
Expand Down
16 changes: 15 additions & 1 deletion custom_components/weatherapi/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from __future__ import annotations

from typing import Any, Mapping

from homeassistant.components.weather import (
ATTR_WEATHER_HUMIDITY,
ATTR_WEATHER_OZONE,
Expand Down Expand Up @@ -35,7 +37,12 @@
from custom_components.weatherapi.const import ATTRIBUTION

from . import WeatherAPIUpdateCoordinator
from .const import ATTR_WEATHER_CONDITION, DATA_FORECAST, DOMAIN
from .const import (
ATTR_REPORTED_CONDITION,
ATTR_WEATHER_CONDITION,
DATA_FORECAST,
DOMAIN,
)

ENTITY_ID_FORMAT = WEATHER_DOMAIN + ".{}"

Expand Down Expand Up @@ -141,3 +148,10 @@ def forecast(self) -> list[Forecast] | None:
def condition(self) -> str | None:
"""Return the current condition."""
return self.coordinator.data.get(ATTR_WEATHER_CONDITION)

@property
def extra_state_attributes(self) -> Mapping[str, Any] | None:
"""Return additional specific state attributes."""
return {
ATTR_REPORTED_CONDITION: self.coordinator.data.get(ATTR_REPORTED_CONDITION)
}

0 comments on commit 39796ac

Please sign in to comment.