diff --git a/homeassistant/components/prometheus/__init__.py b/homeassistant/components/prometheus/__init__.py index 1036eb60cca1..00f93bcfa7d0 100644 --- a/homeassistant/components/prometheus/__init__.py +++ b/homeassistant/components/prometheus/__init__.py @@ -58,6 +58,8 @@ from homeassistant.const import ( ATTR_BATTERY_LEVEL, ATTR_DEVICE_CLASS, ATTR_FRIENDLY_NAME, + ATTR_LATITUDE, + ATTR_LONGITUDE, ATTR_MODE, ATTR_TEMPERATURE, ATTR_UNIT_OF_MEASUREMENT, @@ -71,6 +73,7 @@ from homeassistant.const import ( STATE_OPENING, STATE_UNAVAILABLE, STATE_UNKNOWN, + UnitOfLength, UnitOfTemperature, ) from homeassistant.core import Event, EventStateChangedData, HomeAssistant, State @@ -104,7 +107,7 @@ from homeassistant.helpers.floor_registry import ( ) from homeassistant.helpers.typing import ConfigType from homeassistant.util.dt import as_timestamp -from homeassistant.util.unit_conversion import TemperatureConverter +from homeassistant.util.unit_conversion import DistanceConverter, TemperatureConverter _LOGGER = logging.getLogger(__name__) @@ -771,6 +774,33 @@ class PrometheusMetrics: def _handle_person(self, state: State) -> None: self._numeric_metric(state, "person", "person") + def _handle_geo_location(self, state: State) -> None: + labels = self._labels(state, {"source": state.attributes.get("source", "")}) + if (value := self.state_as_number(state)) is not None: + unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) + if unit is not None: + value = DistanceConverter.convert(value, unit, UnitOfLength.METERS) + self._metric( + "geo_location_distance_meters", + prometheus_client.Gauge, + "Distance of the geo location event from home in meters", + labels, + ).set(value) + if (latitude := state.attributes.get(ATTR_LATITUDE)) is not None: + self._metric( + "geo_location_latitude_degrees", + prometheus_client.Gauge, + "Latitude of the geo location event in degrees", + labels, + ).set(latitude) + if (longitude := state.attributes.get(ATTR_LONGITUDE)) is not None: + self._metric( + "geo_location_longitude_degrees", + prometheus_client.Gauge, + "Longitude of the geo location event in degrees", + labels, + ).set(longitude) + def _handle_lock(self, state: State) -> None: self._numeric_metric(state, "lock", "lock") diff --git a/tests/components/prometheus/test_init.py b/tests/components/prometheus/test_init.py index 140cf2e60363..376a0fdba779 100644 --- a/tests/components/prometheus/test_init.py +++ b/tests/components/prometheus/test_init.py @@ -19,6 +19,7 @@ from homeassistant.components import ( cover, device_tracker, fan, + geo_location, humidifier, input_boolean, input_number, @@ -90,6 +91,7 @@ from homeassistant.const import ( STATE_UNAVAILABLE, STATE_UNKNOWN, UnitOfEnergy, + UnitOfLength, UnitOfTemperature, ) from homeassistant.core import HomeAssistant @@ -1341,6 +1343,39 @@ async def test_person( ).withValue(0.0).assert_in_metrics(body) +@pytest.mark.parametrize("namespace", [""]) +async def test_geo_location( + client: ClientSessionGenerator, + geo_location_entities: dict[str, er.RegistryEntry], +) -> None: + """Test prometheus metrics for geo_location.""" + body = await generate_latest_metrics(client) + + EntityMetric( + metric_name="geo_location_distance_meters", + domain="geo_location", + friendly_name="Earthquake", + entity="geo_location.earthquake", + source="usgs_earthquakes", + ).withValue(25500.0).assert_in_metrics(body) + + EntityMetric( + metric_name="geo_location_latitude_degrees", + domain="geo_location", + friendly_name="Earthquake", + entity="geo_location.earthquake", + source="usgs_earthquakes", + ).withValue(34.05).assert_in_metrics(body) + + EntityMetric( + metric_name="geo_location_longitude_degrees", + domain="geo_location", + friendly_name="Earthquake", + entity="geo_location.earthquake", + source="usgs_earthquakes", + ).withValue(-118.25).assert_in_metrics(body) + + @pytest.mark.parametrize("namespace", [""]) async def test_counter( client: ClientSessionGenerator, counter_entities: dict[str, er.RegistryEntry] @@ -2756,6 +2791,36 @@ async def device_tracker_fixture( return data +@pytest.fixture(name="geo_location_entities") +async def geo_location_fixture( + hass: HomeAssistant, entity_registry: er.EntityRegistry +) -> dict[str, er.RegistryEntry]: + """Simulate geo_location entities.""" + data = {} + geo_location_1 = entity_registry.async_get_or_create( + domain=geo_location.DOMAIN, + platform="test", + unique_id="geo_location_1", + suggested_object_id="earthquake", + original_name="Earthquake", + ) + set_state_with_entry( + hass, + geo_location_1, + 25.5, + { + "source": "usgs_earthquakes", + "latitude": 34.05, + "longitude": -118.25, + "unit_of_measurement": UnitOfLength.KILOMETERS, + }, + ) + data["geo_location_1"] = geo_location_1 + + await hass.async_block_till_done() + return data + + @pytest.fixture(name="counter_entities") async def counter_fixture( hass: HomeAssistant, entity_registry: er.EntityRegistry