Skip to content
Snippets Groups Projects
Unverified Commit 4ee6735c authored by J. Nick Koston's avatar J. Nick Koston Committed by GitHub
Browse files

Small cleanup to zone async_active_zone (#108629)

parent 8d4a1f47
No related branches found
No related tags found
No related merge requests found
"""Support for the definition of zones."""
from __future__ import annotations
from collections.abc import Callable
from collections.abc import Callable, Iterable
import logging
from operator import attrgetter
import sys
from typing import Any, Self, cast
import voluptuous as vol
......@@ -109,40 +110,49 @@ def async_active_zone(
This method must be run in the event loop.
"""
# Sort entity IDs so that we are deterministic if equal distance to 2 zones
min_dist = None
closest = None
min_dist: float = sys.maxsize
closest: State | None = None
# This can be called before async_setup by device tracker
zone_entity_ids: list[str] = hass.data.get(ZONE_ENTITY_IDS, [])
zone_entity_ids: Iterable[str] = hass.data.get(ZONE_ENTITY_IDS, ())
for entity_id in zone_entity_ids:
zone = hass.states.get(entity_id)
if (
not zone
not (zone := hass.states.get(entity_id))
# Skip unavailable zones
or zone.state == STATE_UNAVAILABLE
or zone.attributes.get(ATTR_PASSIVE)
# Skip passive zones
or (zone_attrs := zone.attributes).get(ATTR_PASSIVE)
# Skip zones where we cannot calculate distance
or (
zone_dist := distance(
latitude,
longitude,
zone_attrs[ATTR_LATITUDE],
zone_attrs[ATTR_LONGITUDE],
)
)
is None
# Skip zone that are outside the radius aka the
# lat/long is outside the zone
or not (zone_dist - (radius := zone_attrs[ATTR_RADIUS]) < radius)
):
continue
zone_dist = distance(
latitude,
longitude,
zone.attributes[ATTR_LATITUDE],
zone.attributes[ATTR_LONGITUDE],
)
if zone_dist is None:
# If have a closest and its not closer than the closest skip it
if closest and not (
zone_dist < min_dist
or (
# If same distance, prefer smaller zone
zone_dist == min_dist and radius < closest.attributes[ATTR_RADIUS]
)
):
continue
within_zone = zone_dist - radius < zone.attributes[ATTR_RADIUS]
closer_zone = closest is None or zone_dist < min_dist # type: ignore[unreachable]
smaller_zone = (
zone_dist == min_dist
and zone.attributes[ATTR_RADIUS]
< cast(State, closest).attributes[ATTR_RADIUS]
)
if within_zone and (closer_zone or smaller_zone):
min_dist = zone_dist
closest = zone
# We got here which means it closer than the previous known closest
# or equal distance but this one is smaller.
min_dist = zone_dist
closest = zone
return closest
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment