Skip to content

Commit f8bf7ec

Browse files
tronikosjoostlek
andauthored
Add Google Weather sensors (home-assistant#147141)
Co-authored-by: Joost Lekkerkerker <[email protected]>
1 parent 41e42b9 commit f8bf7ec

File tree

7 files changed

+1395
-2
lines changed

7 files changed

+1395
-2
lines changed

homeassistant/components/google_weather/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
GoogleWeatherSubEntryRuntimeData,
2121
)
2222

23-
_PLATFORMS: list[Platform] = [Platform.WEATHER]
23+
_PLATFORMS: list[Platform] = [Platform.SENSOR, Platform.WEATHER]
2424

2525

2626
async def async_setup_entry(

homeassistant/components/google_weather/entity.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ class GoogleWeatherBaseEntity(Entity):
1616
_attr_has_entity_name = True
1717

1818
def __init__(
19-
self, config_entry: GoogleWeatherConfigEntry, subentry: ConfigSubentry
19+
self,
20+
config_entry: GoogleWeatherConfigEntry,
21+
subentry: ConfigSubentry,
22+
unique_id_suffix: str | None = None,
2023
) -> None:
2124
"""Initialize base entity."""
2225
self._attr_unique_id = subentry.subentry_id
26+
if unique_id_suffix is not None:
27+
self._attr_unique_id += f"_{unique_id_suffix.lower()}"
2328
self._attr_device_info = DeviceInfo(
2429
identifiers={(DOMAIN, subentry.subentry_id)},
2530
name=subentry.title,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"entity": {
3+
"sensor": {
4+
"cloud_coverage": {
5+
"default": "mdi:weather-cloudy"
6+
},
7+
"precipitation_probability": {
8+
"default": "mdi:weather-rainy"
9+
},
10+
"precipitation_qpf": {
11+
"default": "mdi:cup-water"
12+
},
13+
"thunderstorm_probability": {
14+
"default": "mdi:weather-lightning"
15+
},
16+
"uv_index": {
17+
"default": "mdi:weather-sunny-alert"
18+
},
19+
"visibility": {
20+
"default": "mdi:eye"
21+
},
22+
"weather_condition": {
23+
"default": "mdi:card-text-outline"
24+
}
25+
}
26+
}
27+
}
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
"""Support for Google Weather sensors."""
2+
3+
from __future__ import annotations
4+
5+
from collections.abc import Callable
6+
from dataclasses import dataclass
7+
8+
from google_weather_api import CurrentConditionsResponse
9+
10+
from homeassistant.components.sensor import (
11+
SensorDeviceClass,
12+
SensorEntity,
13+
SensorEntityDescription,
14+
SensorStateClass,
15+
)
16+
from homeassistant.config_entries import ConfigSubentry
17+
from homeassistant.const import (
18+
DEGREE,
19+
PERCENTAGE,
20+
UV_INDEX,
21+
UnitOfLength,
22+
UnitOfPressure,
23+
UnitOfSpeed,
24+
UnitOfTemperature,
25+
UnitOfVolumetricFlux,
26+
)
27+
from homeassistant.core import HomeAssistant
28+
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
29+
from homeassistant.helpers.update_coordinator import CoordinatorEntity
30+
31+
from .coordinator import (
32+
GoogleWeatherConfigEntry,
33+
GoogleWeatherCurrentConditionsCoordinator,
34+
)
35+
from .entity import GoogleWeatherBaseEntity
36+
37+
PARALLEL_UPDATES = 0
38+
39+
40+
@dataclass(frozen=True, kw_only=True)
41+
class GoogleWeatherSensorDescription(SensorEntityDescription):
42+
"""Class describing Google Weather sensor entities."""
43+
44+
value_fn: Callable[[CurrentConditionsResponse], str | int | float | None]
45+
46+
47+
SENSOR_TYPES: tuple[GoogleWeatherSensorDescription, ...] = (
48+
GoogleWeatherSensorDescription(
49+
key="temperature",
50+
device_class=SensorDeviceClass.TEMPERATURE,
51+
state_class=SensorStateClass.MEASUREMENT,
52+
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
53+
value_fn=lambda data: data.temperature.degrees,
54+
),
55+
GoogleWeatherSensorDescription(
56+
key="feelsLikeTemperature",
57+
device_class=SensorDeviceClass.TEMPERATURE,
58+
state_class=SensorStateClass.MEASUREMENT,
59+
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
60+
value_fn=lambda data: data.feels_like_temperature.degrees,
61+
translation_key="apparent_temperature",
62+
),
63+
GoogleWeatherSensorDescription(
64+
key="dewPoint",
65+
device_class=SensorDeviceClass.TEMPERATURE,
66+
entity_registry_enabled_default=False,
67+
state_class=SensorStateClass.MEASUREMENT,
68+
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
69+
value_fn=lambda data: data.dew_point.degrees,
70+
translation_key="dew_point",
71+
),
72+
GoogleWeatherSensorDescription(
73+
key="heatIndex",
74+
device_class=SensorDeviceClass.TEMPERATURE,
75+
entity_registry_enabled_default=False,
76+
state_class=SensorStateClass.MEASUREMENT,
77+
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
78+
value_fn=lambda data: data.heat_index.degrees,
79+
translation_key="heat_index",
80+
),
81+
GoogleWeatherSensorDescription(
82+
key="windChill",
83+
device_class=SensorDeviceClass.TEMPERATURE,
84+
entity_registry_enabled_default=False,
85+
state_class=SensorStateClass.MEASUREMENT,
86+
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
87+
value_fn=lambda data: data.wind_chill.degrees,
88+
translation_key="wind_chill",
89+
),
90+
GoogleWeatherSensorDescription(
91+
key="relativeHumidity",
92+
device_class=SensorDeviceClass.HUMIDITY,
93+
state_class=SensorStateClass.MEASUREMENT,
94+
native_unit_of_measurement=PERCENTAGE,
95+
value_fn=lambda data: data.relative_humidity,
96+
),
97+
GoogleWeatherSensorDescription(
98+
key="uvIndex",
99+
entity_registry_enabled_default=False,
100+
state_class=SensorStateClass.MEASUREMENT,
101+
native_unit_of_measurement=UV_INDEX,
102+
value_fn=lambda data: data.uv_index,
103+
translation_key="uv_index",
104+
),
105+
GoogleWeatherSensorDescription(
106+
key="precipitation_probability",
107+
entity_registry_enabled_default=False,
108+
state_class=SensorStateClass.MEASUREMENT,
109+
native_unit_of_measurement=PERCENTAGE,
110+
value_fn=lambda data: data.precipitation.probability.percent,
111+
translation_key="precipitation_probability",
112+
),
113+
GoogleWeatherSensorDescription(
114+
key="precipitation_qpf",
115+
device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
116+
state_class=SensorStateClass.MEASUREMENT,
117+
native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
118+
value_fn=lambda data: data.precipitation.qpf.quantity,
119+
),
120+
GoogleWeatherSensorDescription(
121+
key="thunderstormProbability",
122+
entity_registry_enabled_default=False,
123+
state_class=SensorStateClass.MEASUREMENT,
124+
native_unit_of_measurement=PERCENTAGE,
125+
value_fn=lambda data: data.thunderstorm_probability,
126+
translation_key="thunderstorm_probability",
127+
),
128+
GoogleWeatherSensorDescription(
129+
key="airPressure",
130+
device_class=SensorDeviceClass.ATMOSPHERIC_PRESSURE,
131+
entity_registry_enabled_default=False,
132+
state_class=SensorStateClass.MEASUREMENT,
133+
suggested_display_precision=0,
134+
native_unit_of_measurement=UnitOfPressure.HPA,
135+
value_fn=lambda data: data.air_pressure.mean_sea_level_millibars,
136+
),
137+
GoogleWeatherSensorDescription(
138+
key="wind_direction",
139+
device_class=SensorDeviceClass.WIND_DIRECTION,
140+
entity_registry_enabled_default=False,
141+
state_class=SensorStateClass.MEASUREMENT_ANGLE,
142+
native_unit_of_measurement=DEGREE,
143+
value_fn=lambda data: data.wind.direction.degrees,
144+
),
145+
GoogleWeatherSensorDescription(
146+
key="wind_speed",
147+
device_class=SensorDeviceClass.WIND_SPEED,
148+
entity_registry_enabled_default=False,
149+
state_class=SensorStateClass.MEASUREMENT,
150+
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
151+
value_fn=lambda data: data.wind.speed.value,
152+
),
153+
GoogleWeatherSensorDescription(
154+
key="wind_gust",
155+
device_class=SensorDeviceClass.WIND_SPEED,
156+
entity_registry_enabled_default=False,
157+
state_class=SensorStateClass.MEASUREMENT,
158+
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
159+
value_fn=lambda data: data.wind.gust.value,
160+
translation_key="wind_gust_speed",
161+
),
162+
GoogleWeatherSensorDescription(
163+
key="visibility",
164+
device_class=SensorDeviceClass.DISTANCE,
165+
entity_registry_enabled_default=False,
166+
state_class=SensorStateClass.MEASUREMENT,
167+
native_unit_of_measurement=UnitOfLength.KILOMETERS,
168+
value_fn=lambda data: data.visibility.distance,
169+
translation_key="visibility",
170+
),
171+
GoogleWeatherSensorDescription(
172+
key="cloudCover",
173+
state_class=SensorStateClass.MEASUREMENT,
174+
native_unit_of_measurement=PERCENTAGE,
175+
value_fn=lambda data: data.cloud_cover,
176+
translation_key="cloud_coverage",
177+
),
178+
GoogleWeatherSensorDescription(
179+
key="weatherCondition",
180+
entity_registry_enabled_default=False,
181+
value_fn=lambda data: data.weather_condition.description.text,
182+
translation_key="weather_condition",
183+
),
184+
)
185+
186+
187+
async def async_setup_entry(
188+
hass: HomeAssistant,
189+
entry: GoogleWeatherConfigEntry,
190+
async_add_entities: AddConfigEntryEntitiesCallback,
191+
) -> None:
192+
"""Add Google Weather entities from a config_entry."""
193+
for subentry in entry.subentries.values():
194+
subentry_runtime_data = entry.runtime_data.subentries_runtime_data[
195+
subentry.subentry_id
196+
]
197+
coordinator = subentry_runtime_data.coordinator_observation
198+
async_add_entities(
199+
(
200+
GoogleWeatherSensor(coordinator, subentry, description)
201+
for description in SENSOR_TYPES
202+
if description.value_fn(coordinator.data) is not None
203+
),
204+
config_subentry_id=subentry.subentry_id,
205+
)
206+
207+
208+
class GoogleWeatherSensor(
209+
CoordinatorEntity[GoogleWeatherCurrentConditionsCoordinator],
210+
GoogleWeatherBaseEntity,
211+
SensorEntity,
212+
):
213+
"""Define a Google Weather entity."""
214+
215+
entity_description: GoogleWeatherSensorDescription
216+
217+
def __init__(
218+
self,
219+
coordinator: GoogleWeatherCurrentConditionsCoordinator,
220+
subentry: ConfigSubentry,
221+
description: GoogleWeatherSensorDescription,
222+
) -> None:
223+
"""Initialize."""
224+
super().__init__(coordinator)
225+
GoogleWeatherBaseEntity.__init__(
226+
self, coordinator.config_entry, subentry, description.key
227+
)
228+
self.entity_description = description
229+
230+
@property
231+
def native_value(self) -> str | int | float | None:
232+
"""Return the state."""
233+
return self.entity_description.value_fn(self.coordinator.data)

homeassistant/components/google_weather/strings.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,42 @@
6161
}
6262
}
6363
}
64+
},
65+
"entity": {
66+
"sensor": {
67+
"apparent_temperature": {
68+
"name": "Apparent temperature"
69+
},
70+
"cloud_coverage": {
71+
"name": "Cloud coverage"
72+
},
73+
"dew_point": {
74+
"name": "Dew point"
75+
},
76+
"heat_index": {
77+
"name": "Heat index temperature"
78+
},
79+
"precipitation_probability": {
80+
"name": "Precipitation probability"
81+
},
82+
"thunderstorm_probability": {
83+
"name": "Thunderstorm probability"
84+
},
85+
"uv_index": {
86+
"name": "UV index"
87+
},
88+
"visibility": {
89+
"name": "Visibility"
90+
},
91+
"weather_condition": {
92+
"name": "Weather condition"
93+
},
94+
"wind_chill": {
95+
"name": "Wind chill temperature"
96+
},
97+
"wind_gust_speed": {
98+
"name": "Wind gust speed"
99+
}
100+
}
64101
}
65102
}

0 commit comments

Comments
 (0)