mirror of
https://github.com/home-assistant/core.git
synced 2025-07-15 17:27:10 +00:00
Small cleanup to zone async_active_zone (#108629)
This commit is contained in:
parent
8d4a1f475e
commit
4ee6735cbb
@ -1,9 +1,10 @@
|
|||||||
"""Support for the definition of zones."""
|
"""Support for the definition of zones."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable, Iterable
|
||||||
import logging
|
import logging
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
import sys
|
||||||
from typing import Any, Self, cast
|
from typing import Any, Self, cast
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -109,40 +110,49 @@ def async_active_zone(
|
|||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
"""
|
"""
|
||||||
# Sort entity IDs so that we are deterministic if equal distance to 2 zones
|
# Sort entity IDs so that we are deterministic if equal distance to 2 zones
|
||||||
min_dist = None
|
min_dist: float = sys.maxsize
|
||||||
closest = None
|
closest: State | None = None
|
||||||
|
|
||||||
# This can be called before async_setup by device tracker
|
# 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:
|
for entity_id in zone_entity_ids:
|
||||||
zone = hass.states.get(entity_id)
|
|
||||||
if (
|
if (
|
||||||
not zone
|
not (zone := hass.states.get(entity_id))
|
||||||
|
# Skip unavailable zones
|
||||||
or zone.state == STATE_UNAVAILABLE
|
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
|
continue
|
||||||
|
|
||||||
zone_dist = distance(
|
# If have a closest and its not closer than the closest skip it
|
||||||
latitude,
|
if closest and not (
|
||||||
longitude,
|
zone_dist < min_dist
|
||||||
zone.attributes[ATTR_LATITUDE],
|
or (
|
||||||
zone.attributes[ATTR_LONGITUDE],
|
# If same distance, prefer smaller zone
|
||||||
)
|
zone_dist == min_dist and radius < closest.attributes[ATTR_RADIUS]
|
||||||
|
)
|
||||||
if zone_dist is None:
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
within_zone = zone_dist - radius < zone.attributes[ATTR_RADIUS]
|
# We got here which means it closer than the previous known closest
|
||||||
closer_zone = closest is None or zone_dist < min_dist # type: ignore[unreachable]
|
# or equal distance but this one is smaller.
|
||||||
smaller_zone = (
|
min_dist = zone_dist
|
||||||
zone_dist == min_dist
|
closest = zone
|
||||||
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
|
|
||||||
|
|
||||||
return closest
|
return closest
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user